I have a files students.txt, with lines of the form:

Surname, Forename: Day.Month.Year: Degree

For example:

Smith, John: 15.01.1986: MSc IT
Taylor, Susan: 04.05.1987: MSc IT
Thomas, Steve: 19.04.1986: MSc MIT
Sellen, Jo: 03.07.1987: MSc CSE

How can I change the command below into a sed command to return all the surnames of students who were born in 1987?

$ grep 1987 students.txt | grep -o "^\(.*\),"

3 Answers 3

sed -n '/1987/s/^\([^,]*\),.*$/\1/p' students.txt

or as Glenn pointed out:

sed -n '/1987/s/,.*//p' students.txt
  • A bit simpler: s/,.*// Apr 2, 2011 at 17:53
  • thanks @glenn. You know I was looking my answer yesterday thinking there must be a faster way and then I thought about /1987/,.*/d then I realized ,no, that deletes the entire line. For some reason your answer escaped me.
    – SiegeX
    Apr 2, 2011 at 18:15

If you want to go with awk I would suggest a different answer to Johnsyweb's. The power of awk includes choosing the field separator(s):

awk -F'[,: ]*' '$3 ~ /1987$/ {print $1}' students.txt

But the question was about sed, so I believe SiegeX should get the better vote.

  • > It's nice that you point out that this question is notionally about sed, and probably user5836 must use sed, but one of the good things in this forum is the amount of tangential information that comes from 'related' issues... eg. mentioning the multiple field seperator (-F) is great for me, as I was wondering how to do that with awk... so you get a +1 from me :) with no demerrit implied to the sed answer.... Seeing all the alternatives is good :)
    – Peter.O
    Apr 2, 2011 at 5:55

This kind of problem is well-suited to awk:

% awk '/\.1987:/ {gsub(/,.*/, ""); print}' students.txt 

Or, specifying a column, rather than the whole line (making it easier for you to customise, should you wish to add other columns in :

% awk '/\.1987:/ {
        gsub(/,$/, "", $1);          
        print $1;
}' students.txt
  • I like the fact you made the date more specific than just 1987; to reduce the likelyhood of clashing with 1987 appearing eslewhere in the line.... I've just started using awk, and noticed that in this case, the following will work too (in your first example).... {sub(/,.*/,"")
    – Peter.O
    Apr 2, 2011 at 5:30
  • @fred.bear: Thank you. And thanks for pointing out that I didn't need gsub. The check for 1987 could be localised to the end of column 2, thus: awk -F':' '$2 ~ /\.1987$/ {sub(/,.*/, ""); print}' students.txt
    – johnsyweb
    Apr 2, 2011 at 5:55

You must log in to answer this question.

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