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 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:

12345
2345
7654
5432

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
add comment

3 Answers 3

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]+"
12345
2345
7654
5432

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

share|improve this answer
1  
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
add comment

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
add comment

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#*=}";;
  esac
done
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
add comment

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.