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 parent folder (abeps) which contains several sub folders (1,2,3....25) where output file is located, one in which - all are the same name (opt.out). In this files there is an unpredictable output. This is an example of a line that I need to filter:

A\HF=-1378.9118397\RMSD=4.560e-09\RMSF=1.758e-05\Dipole=0.2110167,0.39

or

978,3.8529967641,3.6669041122\Version=ES64L-G09RevD.01\State=1-A\HF=-

so the thing is I'm interested in getting everything in between \HF= and till \ But they could be on different lines and even HF could be on different lines. So grep wont catch it. Then I tried to write result in a file

grep 'HF=-' abeps/*/opt.out > data

and as result get this

abeps/10/opt.out: 1-A\HF=-1378.9114895\RMSD=5.126e-09\RMSF=5.036

abeps/12/opt.out: \State=1-A\HF=-1378.9185518\RMSD=2.940e-09\RMSF

abeps/13/opt.out: 33413\Version=ES64L-G09RevD.01\State=1-A\HF=-137

share|improve this question
1  
What do you mean exactly by "even HF could be on different lines"? are you saying there may be a newline between the H and the F? –  steeldriver May 26 at 16:19
    
Yes some times. It could be "\HF" on one line or "\H" on one line or even only "\" and "HF" on another. –  Maxim Galkin May 26 at 16:55

3 Answers 3

up vote 2 down vote accepted

If your version of grep supports PCRE (Perl Compatible regular Expressions) you could use Perl's lookbehind and lookahead capabilities

grep -oPz '(?<=\\HF=)(.|\n)+?(?=\\)'

or with pcregrep (if available)

pcregrep -Mo '(?<=\\HF=)(.|\n)+?(?=\\)'

Bear in mind that if your pattern of interest really is split over lines, then the returned text will retain the newline - you may wish to strip it out with tr or sed before using the result.

If the text itself can't be split over lines (only the \HF and \ markers) then you can replace (.|\n)+? by the simpler .+? i.e.

grep -oPz '(?<=\\HF=).+?(?=\\)'

If even the \HF= marker may be split at any point by a newline (as indicated by your comment to the original post), then a slightly different approach is required since PCRE does not currently support variable-length lookbehinds. In that case, you can try

grep -oPz '\\\n?H\n?F\n?=\K(.|\n)+?(?=\\)'

where the lookbehind is replaced by a pseudo-anchor expression using \K

share|improve this answer
    
@MaximGalkin please accept the answer. if your problem is solved. –  harish.venkat May 26 at 16:47
    
grep -oPz '(?<=\\HF=)(.|\n)+?(?=\)' Works very well. Thank you a lot!!! –  Maxim Galkin May 26 at 16:56
    
Add (?s) to have . match \n as well in PCREs. See also \K in newer PCRE versions: grep -oPz '(?s)\\HF=\K.+?(?=\\)' –  Stéphane Chazelas May 26 at 20:47

You could also use sed,

sed -r '/.*HF=([^\]*)\\?.*/s//\1/g' file

Example:

$ echo 'A\HF=-1378.9118397\RMSD=4.560e-09\RMSF=1.758e-05\Dipole=0.2110167,0.39' | sed -r '/.*HF=([^\]*)\\?.*/s//\1/g'
-1378.9118397

$ echo '978,3.8529967641,3.6669041122\Version=ES64L-G09RevD.01\State=1-A\HF=-' | sed -r '/.*HF=([^\]*)\\?.*/s//\1/g'
-
share|improve this answer

With recent pcregrep:

pcregrep -Mo1 '(?s)\\HF=(.*?)\\'
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.