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:




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 won't 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

  • 2
    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? May 26, 2014 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. May 26, 2014 at 16:55

3 Answers 3


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

  • grep -oPz '(?<=\\HF=)(.|\n)+?(?=\)' Works very well. Thank you a lot!!! May 26, 2014 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.+?(?=\\)' May 26, 2014 at 20:47

You could also use sed,

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


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

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

With recent pcregrep:

pcregrep -Mo1 '(?s)\\HF=(.*?)\\'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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