9

I have a input file FILE1.TXT as below.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

I want to search all the fields that belong to a particular Id and get the value for NAME

I managed to loop through each Id and formed the below command for each Id as required.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

The problem here is, I get the output NAME1, in addition to that, I also get NAMEXYZ.

What should be changed so that I only get NAME1 but not NAMEXYZ?

As a workaround, the below commands work.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

Is there any 'switch' or am I missing something?

terdon
  • 234,489
  • 66
  • 447
  • 667
Vinay
  • 193
  • 1
  • 1
  • 8

7 Answers7

6

Use word boundaries:

grep '\bNAME1\b'

would match NAME1 and not NAME1XYZ or XYZNAME1.

Similarly,

sed -n '/11\b/,/14\b/p'

wouldn't match lines containing 111 and 142.


EDIT: It seems that the numbers in the input file are actually line numbers. If that is the case, you could simply say:

sed '11,14!d'

to get the desired lines.

devnull
  • 10,541
  • 2
  • 40
  • 50
  • There is only one `NAME` between the lines 11 and 14. So, why is `sed` looking at `111` and `114`? How to make it not look in between `111` and `114`? – Vinay Mar 03 '14 at 17:11
  • @VinayChalluru See the answer above for how you could modify the `sed` expression. – devnull Mar 03 '14 at 17:12
  • This answers my question I guess. Let me try and let you know. – Vinay Mar 03 '14 at 17:22
  • for word boundaries , `grep` with `-w` flag ? isn't it ? – Rahul Patil Mar 03 '14 at 17:31
  • 1
    @RahulPatil Yup, for the above example `-w` would be equivalent. For the `sed` example, `-w` is slightly different. – devnull Mar 03 '14 at 17:33
  • @RahulPatil At times, it's tough to figure the question. I updated the answer with an option to suit what the _OP probably wanted_. – devnull Mar 03 '14 at 17:38
  • @devnull Thanks for the edit. This might help me next time. But, the numbers are not the line numbers but part of input file. – Vinay Mar 03 '14 at 17:45
  • @VinayChalluru If line numbers aren't part of your input then what made you say _That would save me lot of code lines._ for the `awk` answer. – devnull Mar 03 '14 at 19:10
  • This is not the exact input file and not exactly what I'm doing. I gave a sample with just two fields. Btw, I'll try to do it based on the line numbers in file too. Let me try. – Vinay Mar 04 '14 at 01:28
4

You can use AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

This will look lines between 13 to 17 then search for Name and if match then it will print last word from Name = LastWord

Rahul Patil
  • 24,281
  • 25
  • 80
  • 96
4

You don't need any other tool for this, sed will easily handle it entire.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

That should provide you only with the first sequence of non-whitespace characters following the phrase "NAME = " for every line on which that phrase is found between lines 11 and 14 of any input file sed is fed.

mikeserv
  • 57,448
  • 9
  • 113
  • 229
3

If you know the line numbers you want to search (as your Q suggests), tighten the regex so that you don't match unwanted lines.

For example, change:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

to

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

The ^ will match the beginning of the line and a space after the number guarantees that the specific line number will be matched, and you won't process unwanted blocks.

casey
  • 14,584
  • 5
  • 45
  • 62
3

sed is not the right tool for this job. Use awk where you can specify the id you're looking for and print the next NAME that appears.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
1

you can print those lines which contain matching pattern using sed as follows:

sed -n '/pattern/p'  Filename
  • -n - these options disable this automatic printing, and sed only produces output when explicitly told to via the p command.

  • p - print

techraf
  • 5,831
  • 10
  • 33
  • 51
user182845
  • 39
  • 1
0

generic version not based on line number but id reference

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. load the whole file
  2. clean section not part of the id group (recursive)
  3. just take NAME content value in the group
  4. print the result
NeronLeVelu
  • 360
  • 1
  • 8