Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find a pattern using sed?

How can I combine multiple filters using sed?

Here's my data set

sex,city,age
male,london,32
male,manchester,32
male,oxford,64
female,oxford,23
female,london,33
male,oxford,45

I want to identify all lines which contain MALE AND OXFORD. Here's my approach:

sed -n '/male/,/oxford/p' file

Thanks

like image 358
co7000 Avatar asked Mar 26 '15 19:03

co7000


2 Answers

You can associate a block with the first check and put the second in there. For example:

sed -n '/male/ { /oxford/ p; }' file

Or invert the check and action:

sed '/male/!d; /oxford/!d' file

However, since (as @Jotne points out) lines that contain female also contain male and you probably don't want to match them, the patterns should at least be amended to contain word boundaries:

sed -n '/\<male\>/ { /\<oxford\>/ p; }' file
sed '/\<male\>/!d; /\<oxford\>/!d' file

But since that looks like comma-separated data and the check is probably not meant to test whether someone went to male university, it would probably be best to use a stricter check with awk:

awk -F, '$1 == "male" && $2 == "oxford"' file

This checks not only if a line contains male and oxford but also if they are in the appropriate fields. The same can be achieved, somewhat less prettily, with sed by using

sed '/^male,oxford,/!d' file
like image 70
Wintermute Avatar answered Nov 12 '22 00:11

Wintermute


A single sed command command can be used to solve this. Let's look at two variations of using sed:

$ sed -e 's/^\(male,oxford,.*\)$/\1/;t;d' file
male,oxford,64
male,oxford,45
$ sed -e 's/^male,oxford,\(.*\)$/\1/;t;d' file
64
45

Both have the essentially the same regex:

^male,oxford,.*$

The interesting features are the capture group placement (either the whole line or just the age portion) and the use of ;t;d to discard non matching lines.

By doing it this way, we can avoid the requirement of using awk or grep to solve this problem.

like image 1
Stephen Quan Avatar answered Nov 12 '22 00:11

Stephen Quan