Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
    
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

6 Answers 6

Try something like this:

tr ',' '\n' < file.txt | grep -v \!
share|improve this answer
    
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

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; }'
share|improve this answer

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

share|improve this answer
    
Be careful, the manual says perl regex support is highly experimental... gnu.org/software/grep/manual/html_node/… –  Gowtham Mar 28 '12 at 17:19

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/

share|improve this answer

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
share|improve this answer
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

also there is solution in pure sed

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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