4

I have a csv file like this:

5/05/2017;03;07;30;35;43;01;03
9/05/2017;08;12;16;22;26;06;07
12/05/2017;02;20;28;29;44;03;09
16/05/2017;08;11;15;20;30;03;08
19/05/2017;09;11;12;19;30;04;09
23/05/2017;08;15;25;27;42;01;04
26/05/2017;05;07;26;36;39;02;10
...

that is, a date, plus a series of numbers followed by ;.

I need to remove that date in the first position with a number in sequence starting with 1004... like this:

1004;03;07;30;35;43;01;03
1005;08;12;16;22;26;06;07
1006;02;20;28;29;44;03;09
1007;08;11;15;20;30;03;08
1008;09;11;12;19;30;04;09
1009;08;15;25;27;42;01;04
1010;05;07;26;36;39;02;10
...

I can remove the date using this:

cut -f 2-8 -d';' 2.txt | xargs -I{}

but how do I add a number in sequence replacing the date?

2
  • 2
    That's a delimited text file, but it is not CSV
    – Ben Voigt
    Nov 7, 2017 at 19:28
  • Pipe to nl -s: -i1004?
    – bishop
    Nov 8, 2017 at 3:16

3 Answers 3

9

awk solution:

awk -F';' 'BEGIN{ i=1004 }{ $1=i++ }1' OFS=';' file
  • -F';' - input field separator

  • i=1004 - starting increment

The output:

1004;03;07;30;35;43;01;03
1005;08;12;16;22;26;06;07
1006;02;20;28;29;44;03;09
1007;08;11;15;20;30;03;08
1008;09;11;12;19;30;04;09
1009;08;15;25;27;42;01;04
1010;05;07;26;36;39;02;10

Or you may pass the variable i from "outside":

awk -F';' '{ $1=i++ }1' i=1004 OFS=';' file
2
  • 2
    Nice. Only thing I'd change is to pass the starting value from the shell instead of hardcoding in the awk body: awk -F';' '{$1=i++}1' i=1004 OFS=';' file Nov 7, 2017 at 15:09
  • @glennjackman, you got it Nov 7, 2017 at 15:42
6
  • With awk:

    awk -v cnt=1004 '{ sub("^[^;]+", cnt++) } 1' file.csv
    
  • With shell:

    cnt=1004
    while read -r line; do
        printf '%d;%s\n' $cnt "${line#*;}"
        let cnt++
    done <file.csv
    
  • With jot, paste, and a shell that can handle <(...) redirections:

    paste -d\; <(jot $(wc -l <file.csv) 1004) <(cut -d\; -f2- file.csv)
    
  • With Vim:

    :let cnt=1004 | g/^/ s/^[^;]\+/\=cnt/ | let cnt+=1
    
  • With Perl:

    perl -F\; -lpe 'BEGIN{ $cnt=1004 } $F[0]=$cnt++; $_=join ";", @F' file.csv
    
4
  • note that implicit -a when -F is used requires perl v5.20+ ... can also use perl -F';' -ape 'BEGIN{ $cnt=1004 } s/[^;]+/$cnt++/e' ip.txt
    – Sundeep
    Nov 7, 2017 at 13:00
  • If someone is interested, why and how vim method works, look here: How g makes loop in Vim ex command script.
    – MiniMax
    Nov 7, 2017 at 13:05
  • @Sundeep I'm pretty sure the implicit -a works since at least 5.12 (but I think it wasn't documented until recently). Also, you don't need -F, this works too: perl -lpe 'BEGIN{ $cnt=1004 } s/[^;]+/$cnt++/e' file.csv. But that's identical to the awk approach. Nov 7, 2017 at 13:09
  • oh didn't know that, I just checked perldoc... and yeah the -F wasn't needed
    – Sundeep
    Nov 7, 2017 at 13:27
2

Use Python, it's easy to read, understand, and maintain - and it's available on most Unix installations:

python - << "EOF" > outfilename
for index, line in enumerate(open("filename"), start=1004):
    linedata = line.strip().split(';')
    linedata[0] = str(index)
    print(';'.join(linedata))
EOF

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .