Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file containing some ID (identifier) and DS (description) lines. I'd like to keep the rows containing the string value in their ID line, as well as all the following (related) DS lines before the following ID . For exemple:

ID  number1 string
DS  item11
DS  item12
ID  number2 not_string
DS  item21 
DS  item22
ID  number3 string
DS  item31
DS  item32

Will return:

ID  number1 string
DS  item11
DS  item12
ID  number3 string
DS  item31
DS  item32
share|improve this question

2 Answers 2

up vote 3 down vote accepted

If I understand right, I change the not_string in your input for test:

ID  number1 string                                                              
DS  item11                                                                      
DS  item12                                                                      
ID  number2 qwerty                                                               
DS  item21                                                                      
DS  item22                                                                      
ID  number3 string                                                              
DS  item31                                                                      
DS  item32

Try:

$ awk '/ID/ && !/string/{flag=0;next}/string/{flag=1}flag' file 
ID  number1 string
DS  item11
DS  item12
ID  number3 string
DS  item31
DS  item32
share|improve this answer
sed -n '/ID.* s/p;//,/ID/{//!p;}' <<\DATA                              
    ID  number1 string
    DS  item11
    DS  item12
    ID  number2 not_string
    DS  item21
    DS  item22
    ID  number3 string
    DS  item31
    DS  item32
DATA

That relies on this POSIX defined behavior for sed regex addresses:

If an RE is empty (that is, no pattern is specified) sed shall behave as if the last RE used in the last command applied (either as an /address/ or as part of a s/ubsti/tute/ command) was specified.

When the top of your search is matched by the /ID.* s/ address it is then printed. A line range is specified between the lines matching the last address //,/ID/ and the next ID line. Any lines falling {within;} that range (or an incomplete one if it ends with the last line) that do !not match // are also printed.

All that comes through are the /ID.* s/ lines I explicitly print and all lines occuring between that and the next occurring /ID/ line - or (and including) the last line, whichever comes first.

OUTPUT

ID  number1 string
DS  item11
DS  item12
ID  number3 string
DS  item31
DS  item32
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.