1

My file is in the following format:

this!,is!,another!,test,yes!
this!,is!,another!,column,yes!
no,not!,another!,column

My output should be:

test
column
no

It shouldn't contain the '!' character.

I've tried multiple sed and (e)grep commands but none of them are quite working.

  • Doesn't contain which character? If “!” then the last word why is not included in the sample output? – manatwork Mar 27 '12 at 14:41
  • Yes, sorry. I also updated to add the code blocks for easier reading. – user17000 Mar 27 '12 at 14:46
5

Try something like this:

tr ',' '\n' < file.txt | grep -v \!
  • This doesn't appear to give the output asked for (separates output with newlines instead of spaces). – Chris Down Mar 27 '12 at 14:55
  • the output in the OP's example is separated by newlines. – Tim Kennedy Mar 27 '12 at 14:57
  • @TimKennedy Hm, it wasn't when I looked. – Chris Down Mar 27 '12 at 14:59
  • btw this solution is the best in speed. I've tested all variants from answers and for 5000 iterations tr+grep took 1st place with 16.194s. next one is gnu grep with 19.171s. 3rd place pure sed 20.514s. 4th awk (22.211s), then perl (46.068s) and the last one is shell+sed (714.402s). – rush Mar 27 '12 at 16:25
3

Assuming that you really meant...

test
column
no
column

...here's an awk solution:

awk -v RS=, '{ for (i=1; i<=NF; i++) if($i !~ /!/) print $i; }'
3

requires GNU grep:

grep -oP '(?<=^|,)[^!]+(?=,|$)'

based on your input, that reports:

test
column
no
column

If you don't want "column" to appear twice: grep -oP '(?<=^|,)[^!]+(?=,|$)' | sort -u

2

Perl is made for these kind of tasks. How about this perl (v5.10 and above) one liner:

perl -aF, -nE 'for (@F) { say $_ unless m/!/ }'

  • -a for autosplit mode
  • -F, split input lines on comma
  • -n automatically insert code to iterate over input lines, do not automatically print
  • -E execute supplied per code in the loop

If you have an older perl, just do this: s/-E/-e/, s/say/print/

1

assuming your text file is test.txt, the following:

for word in $(cat test.txt | sed -e 's/,/ /g'); do if [ ! "$( echo "$word" | grep '\!' )" == "$word" ]; then echo "$word"; fi; done

gives me:

test
column
no
column
  • 2
    It's worth noting that process substitution mangles input. (Also, there's no need to create subshells from cat and echo, you can just use herestrings/heredocs.) – Chris Down Mar 27 '12 at 14:58
1

also there is solution in pure sed

sed 's/\([,]\)*[^,]*![^,]*[,]*/\1/g;s/,$//;s/,/\n/g' file.txt

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.