Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Re: getting shell expansion to work

by eserte (Deacon)
on Dec 27, 2007 at 10:08 UTC ( #659183=note: print w/replies, xml ) Need Help??

in reply to getting shell expansion to work

Are you sure your example pattern works? I get only a syntax error with my bash version. But this works: echo mc-lang-[^-]*-[^-]*.rpm This pattern also works when used in perl's system().

Replies are listed 'Best First'.
Re^2: getting shell expansion to work
by perl-diddler (Hermit) on Dec 27, 2007 at 20:24 UTC example got mangled by the plain-text mangler.

    The RE pattern you use, "mc-lang-[^-]*-[^-]*.rpm" says (converting to perl syntax): /mc-lang-[^-].*-[^-].*.rpm/

    The "*", unlike in perl, isn't an "affix count", but matches any string, including the null string.

    I re-edited the base note to use the code tag to display the bash pattern -- it included square brackets inside of the parens.

    I was trying to use the regular expression syntax from bash to match "one or more" of an item. From the bash man page:

    If the extglob shell option is enabled using the shopt builtin, + several extended pattern matching operators are recognized. In the f +ollowing description, a pattern-list is a list of one or more patterns s +eparated by a |. Composite patterns may be formed using one or more of +the fol- lowing sub-patterns: ?(pattern-list) Matches zero or one occurrence of the given patte +rns *(pattern-list) Matches zero or more occurrences of the given pat +terns +(pattern-list) Matches one or more occurrences of the given patt +erns @(pattern-list) Matches one of the given patterns !(pattern-list) Matches anything except one of the given patterns
    As near as I can tell, perl doesn't have a similar syntax for RE's. It might be better for me to repost the base note with better wording/phrasing and a better example, since the example I used doesn't demonstrate my problem (and doesn't actually solve my my problem either, I just found out...:-( ).

    What I want to do *may* not be doable, directly, using a bash expression -- since I'm not sure if the pattern matching in bash can control "greediness".

      I was trying to use the regular expression syntax from bash to match "one or more" of an item. (...) If the extglob shell option is enabled (...)

      Thing is, you have to explicitly enable extended pattern matching, which is not enabled by default when the shell is run in non-interactive mode.

      Both of these invocations do work for me:

      my $r = `/bin/bash -O extglob -c 'echo mc-lang-+([^-])-+([^-])*.rpm'`; my $r = `/bin/bash -c 'shopt -s extglob\necho mc-lang-+([^-])-+([^-])* +.rpm'`;

      (i.e., print $r would output mc-lang-4.6.1-140.x86_64.rpm, assuming a file with that name is in the current directory)

      Note that when enabling extglob within the command sequence itself (shopt -s extglob, as opposed to the startup option -O extglob), you have to use \n as the statement separator, because when using a semicolon, the shell would parse the line in one go, and produce a syntax error before the shopt command gets a chance to take effect...

      Interestingly, on Linux (where /bin/sh typically is a symlink to /bin/bash), the following does work too, for me:

      my $r = `shopt -s extglob\necho mc-lang-+([^-])-+([^-])*.rpm`;

      I say "interestingly", because when invoked through the name sh (as Perl does behind the scenes), bash will behave differently in several respects (i.e. it mimics the original bourne shell), which is why I would have expected it to not do extended pattern matching at all. Apparently, the latter is not the case.

        Gold star (or ++ points in monk-speak :-)).
        I wondered about that semicolon and the order of processing things -- my only concern (in some 'general' case, not my particular problem) about using "\n" might be portability to a platform where "\n" wasn't the line delimiter.... I should have just "tried it".

        I too am minorly surprised that '/bin/sh' allows the the non-posix extensions... Definitely not something to rely on...

        Another solution that I ran across was to use bash as a 'filter' of sorts:

        $pat='+([^-])-+([^-]).rpm'; $a=`echo 'echo gcc-$pat'|bash -O extglob`; #-O=capital 'O'
        It sorta *bums* me that 'semicolon' isn't equivalent to '\n' in this case. There might be a bug there, somehow: if "shopt cmdhist"=on, then bash tries to store multiline commands in one history entry. Then, if "shopt lithist" is off (I think that's default), then bash will store multi-line commands separated by a semicolon (instead of the newline which would have separated the commands of the multi-line command). As you point out, this isn't equivalent to separation by a newline.

        It would be a rare error case, but if one concocted a multi-line command that turned on 'extglob'bing, followed by its usage, then that multi-line command sequence would be stored with semi-colons, so on recall, it would contain the non-working semi's instead of the requisite newlines... (and people wonder how it is that I so often break things...:-) )

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://659183]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2017-05-01 02:27 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (544 votes). Check out past polls.