6

My input file is like this:

IDno="1"
Name=Jack
Type=Student
IDno="2"
Name=Jill
Type=Teacher

I am using sed to extract all the IDno and the type only when type is student.

sed -e '/IDno=/b' -e '/Type=Student/b' d

This gets me all lines with type student but not the IDnos.

I want to get

IDno="1"
Type=Student
IDno="2"

but I am getting

Type=Student

What am I doing wrong?

2
  • Wouldn't egrep be easier? egrep -e "IDno=|Type=Student" inputfile
    – Terrance
    Feb 27, 2017 at 5:49
  • 1
    Did you mean to write -e d (not just d)? otherwise the command is malformed I think. Regardless, it would be more idiomatic to invert the logic using ! rather than by branching past the d i.e. sed '/IDno=\|Type=Student/!d' Feb 27, 2017 at 13:06

4 Answers 4

4

egrep can get multiple lines from a file. Using a pipe | as a separator you can pull as many different criteria as you want. egrep is the equivalent of grep -E. egrep is a script found in the /bin folder with the contents pointing to exec grep -E "$@".

Example:

egrep "IDno=|Type=Student" inputfile

or

grep -E "IDno=|Type=Student" inputfile

Should output:

IDno="1"
Type=Student
IDno="2"

Hope this helps!

4
  • 2
    egrep is deprecated in favor of grep -E, it's time to get rid of the cliché...
    – heemayl
    Feb 27, 2017 at 14:04
  • This return every single "IDno=" line, regardless of whether or not the "Type=Student" two lines down. That appeared to be part of the original question, to only return IDno's for "Student"s, but the OP seems to like this, so...?
    – Xen2050
    Feb 27, 2017 at 14:08
  • That is good, pipeing it back to grep again to only return the ID & Type lines gets rid of the Name too (and the -- separator line), like adding |grep "IDno=\|Type="
    – Xen2050
    Feb 27, 2017 at 14:48
  • @heemayl Good point! =) Old habits die hard I guess. Maybe one day they'll remove the script, but from my understanding is that it is left in there for older applications that rely on them to not be modified.
    – Terrance
    Feb 27, 2017 at 15:25
4

With sed, to print specific lines, it's easier to use the -n option and the p command:

sed -rn '/IDno=|Type=Student/p'

Or:

sed -n -e '/IDno=/p' -e '/Type=Student/p'

The -n option suppresses output unless explicitly print. The p command, of course, prints matching lines.

3
  • awk:

    Setting the field separator as =, and printing the records that contain Type=Student as the whole record or IDno as the first field:

    awk -F= '$1=="IDno" || $0=="Type=Student"'
    
  • perl:

    Printing the lines that start with IDno followed by =, or start with Type, followed by a = and end in Student:

    perl -ne 'print if /^(IDno=|Type=Student$)/'
    

Example:

% cat file.txt                                  
IDno="1"
Name=Jack
Type=Student
IDno="2"
Name=Jill
Type=Teacher

% awk -F= '$1=="IDno" || $0=="Type=Student"' file.txt
IDno="1"
Type=Student
IDno="2"

% perl -ne 'print if /^(IDno=|Type=Student$)/' file.txt
IDno="1"
Type=Student
IDno="2"
0

The original question seems to ask "to extract all the IDno and the type only when type is student." But the example output returns all IDno= lines, so that's rather contradictory...

Here's an answer that only returns the IDno's and Type's when the Type=Student.

sed -n 'N;N;/IDno=.*Type=Student/p' filename | grep -v "^Name="

A little explanation:

  • -n, --quiet, --silent suppress automatic printing of pattern space
  • N;N; Read/append the next line of input into the pattern space. (twice)
  • /IDno=.*Type=Student/p find & print from IDno= to Type=Student
  • | grep -v "^Name=" don't show the Name= line

I don't like the sed|grep, but not too sure how to get sed to re-search it's output, and a pipe generally says "take this output and do something"... Could do grep|sed too

grep -v "^Name=" t | sed -n 'N;N;/IDno=.*Type=Student/p'
3
  • The example output clarifies that.
    – muru
    Feb 27, 2017 at 14:23
  • @muru Thanks, I just noticed that too, seems to be a mistake IMO either in the description or example output. Actually found a mistake in my answer too, pasting the Name after ID... Maybe someone will find this answer useful anyway (especially after/if I fix it), I'm still learning from it\
    – Xen2050
    Feb 27, 2017 at 14:38
  • 2
    read it this way "(all the IDno) and (the type only when type is student)"
    – muru
    Feb 27, 2017 at 15:07

You must log in to answer this question.