0

Given an input like this

this,is,a,test,string,containing,multiple
lines,of,string,with,numb3rs,and,w0rds

I want to delete every second and fourth word in each line using sed. Words are strictly alphanumeric.

5
  • "Every 2nd word" would include the 4th word. Do you mean "the 2nd and 4th word on each line"?
    – Kusalananda
    Apr 19 '20 at 9:12
  • Sorry, I did not specify more precisely. I meant exactly the 2nd and 4th word on each line.
    – Paralyz3d
    Apr 19 '20 at 9:15
  • Do you want to remove only the 2nd/4th word even though a field may contain multiple words? Or does a field only ever contain a single word?
    – Kusalananda
    Apr 19 '20 at 9:42
  • 1
    Should the separating commas be removed, too? Please add a sample output.
    – FelixJN
    Apr 19 '20 at 11:33
  • Please show us your expected output. "Every second word" means you want to delete the 2nd, 4th, 6th, 8th etc. "Every fourth" would mean deleting the 4th, 8th, 12th, 16th etc. Without an example output it's very hard to understand what you mean.
    – terdon
    Apr 19 '20 at 13:12
4

The most natural tool for this is cut.

cut -d , -f 1,3,5-

With sed, use \([^,]*,\) to match one field.

sed 's/^\([^,]*,\)\([^,]*,\)\([^,]*,\)\([^,]*,\)/\1\3/'
2
  • Or sed 's/^\([^,]*,\)[^,]*,\([^,]*,\)[^,]*,/\1\2/'. Note that the sed ones assume all lines have at least 5 fields. sed 's/,[^,]*//3; s/,[^,]*//' would take care of those. Apr 19 '20 at 12:19
  • What if you want the second and the 113th ? Should you write a very long request?
    – Sandburg
    Oct 6 '20 at 13:28
1

it's not sed, but you can use Miller (https://github.com/johnkerl/miller) and run

<input mlr --csv -N unsparsify then cut -x -f 2,4

to have

this,a,string,containing,multiple
lines,string,numb3rs,and,w0rds
0

If you just want to remove the 2nd and 4th fields on each line, you can do:

$ perl -F, -lane 'print join ",", @F[0,2,4..$#F]' file
this,a,string,containing,multiple
lines,string,numb3rs,and,w0rds

The -n tells perl to read an input file and apply the script given by -e to each line. The -a causes perl to act like awk and split its input on the character given by -F and save the result in the array @F. Then, join ",",@F[0,2,4..$#F]' makes a new string by joining the 1st and 3rd fields (arrays start from 0) and then the 5th field and everything else until the end of the array ($#F is the highest index in the array), and the print print this string.

0
awk '{ split($0,a,","); delete a[4]; delete a[2]; for (i=1;i<=length(a); i++){ if(a[i]!="") printf "%s,", a[i] }; printf "\n";}' inputfile

This second one does not work, despite this line in man gawk:

Assigning a value to an existing field causes the whole record to be rebuilt when $0 is referenced. Similarly, assigning a value to $0 causes the record to be resplit, creating new values for the fields.

gawk 'BEGIN{ FS=","; OFS="," }{ $2=""; $4=""; a=$0; $0=a; print $0 }' inputfile

EDIT: Above does not work because of the FS and gow awk handles them, and that's why this works:

gawk 'BEGIN{ FS=","; OFS="," }{ gsub(FS $2,""); gsub(FS $4,""); print $0 }'

output:

this,a,test,containing,multiple
lines,string,with,and,w0rds
2
  • @Cyrus, but this, indeed shorter, version will output this,,a,,string,, so two commas after this, which is same as my last version.
    – Luuk
    Apr 19 '20 at 12:18
  • added an edit with working second version...
    – Luuk
    Apr 20 '20 at 6:01

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.