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
  • 242,166
Vinay
  • 193

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,691
  • 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,711
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
  • 58,310
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,754
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
  • 85,964
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,941
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