Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 Jun 2012 22:23:57 +0200
From:      Giorgos Keramidas <keramida@ceid.upatras.gr>
To:        Aleksandr Miroslav <alexmiroslav@gmail.com>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: shell scripting: grepping multiple patterns, logically ANDed
Message-ID:  <xeiabok08s6a.fsf@kobe.laptop>
In-Reply-To: <CACcSE1zwRcU_VQ16A2wiG4yWk4RBRykTXBono3xspw97zhDs7w@mail.gmail.com> (Aleksandr Miroslav's message of "Wed, 27 Jun 2012 10:25:46 -0400")
References:  <CACcSE1zwRcU_VQ16A2wiG4yWk4RBRykTXBono3xspw97zhDs7w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 27 Jun 2012 10:25:46 -0400, Aleksandr Miroslav <alexmiroslav@gmail.com> wrote:
> hello,
>
> I'm not sure if this is the right forum for this question, but here
> goes.
>
> I have the following in a shell script:
>
>     #!/bin/sh
>
>     if [ "$#" -eq "0" ]; then
>             find /foo
>     fi
>     if [ "$#" -eq "1" ]; then
>             find /foo | grep -i $1
>     fi
>     if [ "$#" -eq "2" ]; then
>             find /foo | grep -i $1 | grep -i $2
>     fi
>     if [ "$#" -eq "3" ]; then
>             find /foo | grep -i $1 | grep -i $2 | grep -i $3
>     fi
>
> Is there an easier/shorter way to do this? If there are 15 arguments
> supplied on the command line, I don't necessarily want to build 15 if
> statements.

The solutions proposed so far are ok, if you really *have* to stick to a
shell script.  For safer regexp pattern construction I'd probably
convert the script to some language that makes it less easy to shoot
yourself in the foot because you missed a quote or because you happened
to choose "'" as the quoting character and one of the patterns includes
it too.

I'd write this sort of logic in python, constructing 'regexp' patterns
on the go from the command-line arguments:

    #!/usr/bin/env python
    
    import sys
    import re
    
    if __name__ == '__main__':
        pattern = '^.*$'            # Match everything by default
        matcher = None
        if len(sys.argv) > 1:
            pattern = (
                r'^.*(' +
                '|'.join(map(lambda part: r'' + part,
                             sys.argv[1:])) +
                ').*$')
        try:
            # print 'pattern = %s' % pattern
            matcher = re.compile(pattern)
        except:
            sys.stderr.write('invalid pattern: %s' % pattern)
            sys.exit(1)
        for line in sys.stdin.readlines():
            # print '# line = "%s", match = %s' % (
            #     line.rstrip(), matcher.match(line))
            if matcher.match(line):
                line = line.rstrip()
                print '%s' % line

This should be able to match even patterns with quotes embedded, e.g.:

  0630 22:21 kobe:~$ ./foo.py "it's dark"
  When it's dark,  
  the world is normally
  a quieter place
  When it's dark
  ^D
  When it's dark,
  When it's dark
  0630 22:22 kobe:~$ 




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?xeiabok08s6a.fsf>