5

Each line in a comma-separated file has 5 fields.

a,b,c,d,e
f,g,c,i,
j,k,c,m,n
o,p,c,r,s
t,u,c,w,
x,y,z,aa,bb

How can I extract the lines which have c in the 3rd field and their 5th field is NOT empty? The result would be:

a,b,c,d,e
j,k,c,m,n
o,p,c,r,s
1
  • We always like to see, what you tried in order to help you find the solution on your own. Otherwise it looks like you want to us to solve your homework for you.
    – Minix
    May 30, 2015 at 22:25

5 Answers 5

8

Possible solution with awk:

awk -F',' '$3 == "c" && $5' file

Depending on actual data this may not work as desired as mentioned in comments (thanks Janis for pointing this: it will miss f,g,c,i,0 e.g 5th field is 0) so you can do following:

awk -F',' '$3 == "c" && $5 != ""' file

And as this is the accepted answer I am adding not so obvious forcing 5th field to string (as in cuonglm(+1) solution):

awk -F',' '$3 == "c" && $5""' file
3
  • 4
    Note that, depending on the actual data, this may not work as desired. It would not match f,g,c,i,0, i.e. with a 0 in the last column. The fix is of course easy: awk -F',' '$3 == "c" && $5 != "".
    – Janis
    May 31, 2015 at 0:39
  • @Janis: $5"" is enough. See my answer
    – cuonglm
    May 31, 2015 at 4:36
  • 1
    @cuonglm; Yes, forcing the field to string is also possible. But, IMO, it's still less clear than spending two more characters to create the explicit and (also to awk beginners!) more obvious condition $5!="".
    – Janis
    May 31, 2015 at 5:20
3
sed -n '/,$/!s/^\([^,]*,\)\{2\}c/&/p'

...will work for a POSIX sed. If you can use a sed which implements AT&T Augmented regular expressions - such as the one freely available in the astopen package - you could do it like:

sed -nX '/^(([^,]*,){2}c.*)&(.*,)!$/p'

Of course, if the latter case is true, you probably have a similar grep (as can be compiled as a ksh93 builtin, incidentally) and so you should probably do instead:

grep -xX '(([^,]*,){2}c.*)&(.*,)!'
2
  • Your sed logic is insufficient: you're just checking that the line does not end with a comma, not whether the 5th field is not empty. You'll miss a line like a,b,c,d,e, Jun 1, 2015 at 17:04
  • @glennjackman - Not at all. The description of the file is: Each line in a comma-separated file has 5 fields. Admittedly if that were not the case an additional test like 's/,//5;t' might be called for.
    – mikeserv
    Jun 1, 2015 at 17:08
2

With awk:

awk -F, '$3 == "c" && $5""' file

In awk, 0 and "" are two false values in boolean context. So if you do something like $3 == "c" && $5, you will miss lines which the fifth field is 0. $5"" force awk coerce fifth field to string, string "0" will be evaluated to true.

0

With perl you could do something like:

perl -F, -nlae 'print if $F[2] eq "c" and $F[4] ne ""'

The -a option splits the lines by the delimiter specified by the -F option and you can afterwards simply check the fields in the @F array.

0

Using python:

#!/usr/bin/env python2
with open('file.txt') as f:
    for line in f:
        fields = line.rstrip().split(',')
        if fields[2] == 'c' and fields[4]:
            print line.rstrip()

Here we have taken the fields of each line splitted on comma (,) into a list (fields) and then we have checked the conditions on the required fields.

2
  • I would assign the rstrip() to a new variable and the output from split as well and re-use that for as more readable and faster solution
    – Anthon
    May 31, 2015 at 5:06
  • @Anthon yeah, you are right..answer edited..
    – heemayl
    May 31, 2015 at 13:15

You must log in to answer this question.

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