Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a large text file that is all one line. In the text are several sections that looks like foo=12345 and I need to extract them all as separate lines, ignoring the rest of the file.

For example:

random junk foo=12345 more junk random junk foo=2345 junk foo=7654 junk random foo=5432 junk

What I want to get out is:


I know how to write the regex to extract the foo=([0-9]+), but I'm not sure how to apply that to the text and get the lines out in bash.

share|improve this question
up vote 3 down vote accepted
$> echo "random junk foo=12345 more junk random junk foo=2345 junk foo=7654 junk random foo=5432 junk" | grep --only-matching --perl-regexp "(?<=foo=)[0-9]+"

What we've done here is use lookbehind regex in "(?<=foo=)[0-9]+".

share|improve this answer
Note that the --perl-regexp option is available to GNU versions of grep. Non-Linux systems may not default to the GNU version. – Arcege Feb 26 '12 at 20:19
According to the perlre man page, you can also write this regex as foo=\K[0-9]+, which may be "significantly more efficient". – camh Feb 26 '12 at 20:21
Great! This works perfectly. I'm on OS X, btw. – Roger Gilbrat Feb 26 '12 at 22:03

I'd use awk to parse the long line into records.

awk 'BEGIN{FS="=";RS=" "}/^foo=/{print $2}'

This sets each "word" as a separate record, and within that word, to separate fields with '='. Then just output the right side of the '=' when the left side is "foo". Need to use the regexp instead of $1=="foo" since if there is no '=', the first field is the same as the entire record.

share|improve this answer

You can do this with shell constructs alone: read the data into a variable, then split this variable at the characters in $IFS (whitespace by default) and retain the chunks that you want. A variable substitution outside double quotes undergoes word splitting (which we want here) and filename generation (a.k.a. globbing, which we don't want), so turn off globbing with set +f first.

set +f
for x in $(cat /path/to/file); do
  case "$x" in
    foo=*) echo "${x#*=}";;
set -f

Instead of calling cat, you can use the read builtin.

set +f
read -r line </path/to/file
for x in $line; do …
share|improve this answer

Your Answer


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.