home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!sdd.hp.com!usc!nic!netlabs!lwall
- From: lwall@netlabs.com (Larry Wall)
- Newsgroups: comp.unix.questions
- Subject: Re: Regular Expressions with [fe]grep (AGAIN)
- Message-ID: <1992Jul31.065335.22660@netlabs.com>
- Date: 31 Jul 92 06:53:35 GMT
- References: <1992Jul30.110331.3647@news.acns.nwu.edu>
- Sender: news@netlabs.com
- Organization: NetLabs, Inc.
- Lines: 82
- Nntp-Posting-Host: scalpel.netlabs.com
-
- In article <1992Jul30.110331.3647@news.acns.nwu.edu> navarra@casbah.acns.nwu.edu (John Navarra) writes:
- : Now, however, I want to change each '0' to a '123':
- :
- : 123
- : 123123
- : 123123123
- : 123123123123
- : 123123123123123
- : 123123123123123123
- : 123123123123123123123
- :
- : and I want to get the same results with the pattern matching.
- : I want to print out the lines with one string of '123', the
- : lines with two strings of '123', or at least 1 but no more than
- : 3 strings of '123'
- :
- : Is there some way using a form of grep to do this? Egrep has '()' grouping
- : but doesn't have the \{n,m\} stuff. And grep has the opposite. Grrr.
-
- Outa luck with *grep. Sorry. Perl does what you expect:
-
- perl -ne "print if /^(123){1}$/"
- perl -ne "print if /^(123){2}$/"
- perl -ne "print if /^(123){1,3}$/"
-
- : Secondly, what if my file looked like:
- :
- : 123.105.113.13
- : 123.123.113.13
- : 123.123.123.13
- : 123.123.123.123
- :
- : How would I print out the lines matching the following conditions:
- : 1) only one occurence of '123'
-
- That's problematical, because you can't anchor with ^ and $ to keep
- from matching lines with more than you're interested in. Did you
- mean consecutive occurrences? Then you can say
-
- perl -ne 'print if /(123\.?)+/ && length($&) <= 4'
-
- : 2) two or more occurences of '123'
-
- perl -ne 'print if /(123\.?){2,}/ && length($&) <= 8'
-
- : 3) at least two but no more than 4 occurences of '123'.
-
- perl -ne 'print if /(123\.?){2,}/ && length($&) <= 16'
-
- If I were forced to do it in sed, I'd do something tricksy like
-
- s/$/./;
- s/123\./X/g
- /X\{2,4\}/!d
- s/X/123./
- s/\.$//
-
- It becomes somewhat simpler if you don't require consecutive
- occurrences, since Perl's substitute operator will return how many
- substitutions it did. (I presume that you only want 123 as a complete
- "word", so I've used \b to assert word boundaries here.)
-
- : 1) only one occurence of '123'
-
- perl -ne 'print if s/\b123\b/123/g == 1'
-
- : 2) two or more occurences of '123'
-
- perl -ne 'print if s/\b123\b/123/g >= 2'
-
- : 3) at least two but no more than 4 occurences of '123'.
-
- perl -ne '$count = s/\b123\b/123/g; print if $count >= 2 && $count <= 4'
-
- In recent versions of Perl you can also do it with a g modifier on
- an ordinary pattern match:
-
- perl -ne '@c = /\b123\b/g; print if @c == 1'
- etc.
-
- Larry Wall
- lwall@netlabs.com
-