co7000
co7000

Reputation: 221

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

Upvotes: 7

Views: 72508

Answers (3)

Stephen Quan
Stephen Quan

Reputation: 25871

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.

Upvotes: 1

Wintermute
Wintermute

Reputation: 44023

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

Upvotes: 8

Jotne
Jotne

Reputation: 41446

You can use awk

awk -F, '/\<male\>/ && /\<oxford\>/' file
male,oxford,64
male,oxford,45

It uses the word anchor to prevent hit on female.

Upvotes: 0

Related Questions