4

What's the simplest way to print all matches (either one line per match or one line per line of input) to a regular expression on a unix command line? Note that there may be 0 or more than 1 match per line of input.

I assume there must be some way to do this with sed, awk, grep, and/or perl, and I'm hoping for a simple command line solution so it will show up in my bash history when needed in the future.

EDIT: To clarify, I do not want to print all matching lines, only the matches to the regular expression. For example, a line might have 1000 characters, but there are only two 10-character matches to the regular expression. I'm only interested in those two 10-character matches.

jonderry
  • 23,013
  • 32
  • 104
  • 171
  • to a regex? I presume you mean of a regex – matchew Jun 07 '11 at 01:20
  • 1
    Sorry, could you expand a bit on what you want? On the surface, this just sounds like a bare-bones 'grep', but I know that can't be all there is to it. :) – Brian Gerard Jun 07 '11 at 01:21
  • Suppose the input is "fod,food,fad\nbar\nfoooood\n" and the regular expression is "fo*d". Then the output should be "fod\nfood\nfoooood\n", or "fodfood\n\nfoooood\n". – jonderry Jun 07 '11 at 01:25

4 Answers4

15

Assuming you only use non-capturing parentheses,

perl -wnE'say /yourregex/g'

or

perl -wnE'say for /yourregex/g'

Sample use:

$ echo -ne 'fod,food,fad\nbar\nfooooood\n' | perl -wnE'say for /fo*d/g'
fod
food
fooooood
$ echo -ne 'fod,food,fad\nbar\nfooooood\n' | perl -wnE'say /fo*d/g'
fodfood

fooooood
ysth
  • 96,171
  • 6
  • 121
  • 214
  • 2
    Just noticed that `grep -o 'fo*d' input.txt` seems to work as well. Color can be removed with `--color=never` if necessary. – jonderry Jun 07 '11 at 02:16
7

Unless I misunderstand your question, the following will do the trick

grep -o 'fo.*d' input.txt

For more details see:

Tom Howard
  • 6,516
  • 35
  • 58
1

Going off the comment, and assuming you're passed the input from a pipe or otherwise on STDIN:

perl -e 'my $re=shift;$re=~qr{$re};while(<STDIN>){if(/($re)/g){print"$1\n"}while(m/\G.*?($re)/g){print"$1\n"}}'

Usage:

cat SOME_TEXT_FILE | perl -e 'my $re=shift;$re=~qr{$re};while(<STDIN>){if(/($re)/g){print"$1\n"}while(m/\G.*?($re)/g){print"$1\n"}}' 'YOUR_REGEX'

or I would just stuff that whole mess into a bash function...

bggrep ()
{
    if [ "x$1" != "x" ]; then
        perl -e 'my $re=shift;$re=~qr{$re};while(<STDIN>){if(/($re)/g){print"$1\n"}while(m/\G.*?($re)/g){print"$1\n"}}' $1;
    else
        echo "Usage: bggrep <regex>";
    fi
}

Usage is the same, just cleaner-looking:

cat SOME_TEXT_FILE | bggrep 'YOUR_REGEX'

(or just type the command itself and enter the text to match line-by-line, but that didn't seem a likely use case :).

Example (from your comment):

bash$ cat garbage
fod,food,fad
bar
fooooooood
bash$ cat garbage | perl -e 'my $re=shift;$re=~qr{$re};while(<STDIN>){if(/($re)/g){print"$1\n"}while(m/\G.*?($re)/g){print"$1\n"}}' 'fo*d'
fod
food
fooooooood

or...

bash$ cat garbage | bggrep 'fo*d'
fod
food
fooooooood
Brian Gerard
  • 885
  • 6
  • 13
1
perl -MSmart::Comments -ne '@a=m/(...)/g;print;' -e '### @a'
Axeman
  • 29,660
  • 2
  • 47
  • 102