I have data in csv format:


My desired output:


How can I do this?

  • 5
    Please edit your question and explain what you need in words. Presumably, you don't want a command that simply prints 7012,879456217,7065,758964231, so please explain how you get from your input to your desired output. Also, please use the formatting tools to format your posts. – terdon Feb 13 at 11:54

Something like can do the work:

awk -F, '{for (i=1;i<NF-1;i++) if (length($i)==4 && int($i)==$i) printf("%s,%s,", $i,$(i+1))}' input_file

If you want the "absolute overkill" version which removes unnecessary , and adds newlines to the output, try

awk -F, '{if (g) printf("\n"); f=0; for (i=1;i<NF-1;i++) if (length($i)==4 && int($i)==$i) {if (f) printf(","); else f=1; printf("%s,%s", $i,$(i+1)); g=1}} END{if (g) printf("\n")}' input_file
|improve this answer|||||
  • 1
    You could modify it to do that, though, by replacing if (length($i)==4) with if ($i ~ /[0-9][0-9][0-9][0-9]/) (portable, with collation locale set to C) or if ($i ~ /[[:digit:]]{4}/) (GNU awk only). BTW, I think you mistyped the FS, it should be ,, not ;. – AdminBee Feb 13 at 12:33
  • Thanks but Syntax error: near %s – Amit10504 Feb 13 at 12:39
  • yes I have changed the FS but this is throwing syntax error – Amit10504 Feb 13 at 12:41
  • 2
    @Amit10504 There seems to be one stray " in the awk command and one " missing. Try removing the " after the 4 and modify the printf command to printf("%s,%s",$i,$(i+1)). – AdminBee Feb 13 at 12:41
  • 1
    Got it thanks printf("%s,%s"",",$i,$(i+1)).... It worked as expected with this. Thankyou so much for your help... Really appricate your help@AdminBee – Amit10504 Feb 13 at 12:54

If your file never contains quoted commas or newlines, you can just use cut:

cut -d, -f3,4,6,7 file.csv
  • -d specifies the delimiter
  • -f specifies the columns to output
|improve this answer|||||
  • 1
    Based on the title and some creative guessing, I think the OP only want to print fields whose length is exactly 4 and the field immediately after those. – terdon Feb 13 at 12:05
  • Yes terdon you are right.. 4 digit number is random it can come in any place and I need the number and the field immediately after those – Amit10504 Feb 13 at 12:27
  • 1
    @Amit10504 then please edit your question and clarify as I requested almost an hour ago! Otherwise, people will waste their time, and yours, giving answers that don't help you. – terdon Feb 13 at 12:35
  • Also, what should happen if the last number has length 4? What if the numbers of length 4 are consecutive, e.g. 1234,1234,123456? – choroba Feb 13 at 12:53
ruby -rcsv -e '
  CSV.foreach(ARGV.shift) do |row|
    puts row.each_cons(2)
            .select {|pair| pair.first =~ /^\d{4}$/}
' file.csv
|improve this answer|||||

You may do it multiple ways:

Method-1: GNU sed(extended regex enabled)

Explained: Initially place a marker at the beginning of pattern space. Look two fields to the right and if we see a 4-digit number to our immediate right, make the marker jump two fields to the right. OTW, make the marker jump one field AND erase the field from the pattern space. This process stops when the marker reaches the end of pattern space.At that point whatever's left in the pattern space is the answer.

$ sed -re '
 ' file.csv

$ perl -F, -lane '$,=",";
    print  /(?:^|,)(\d{4},[^,]+)/g;
' file.csv 

$ perl -F, -lane '$,=",";
    shift(@F) =~ /^(\d{4})$/
      and push(@A, $1, shift(@F))
        while @F > 1;
    print splice @A if @A;
' file.csv

$ awk -F, -vOFS=, '{
    N = split($0, a, FS)
    $0 = ""
    for ( i=j=1; i<N; )
      if ( a[i] ~ /^[0-9]{4}$/ )
        for ( k=0; k<2; k++ )
          $(j++) = a[i++]
  }NF' file.csv
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.