Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: ${name/pattern/repl} with negated pattern



On May 15,  2:26pm, Roman Neuhauser wrote:
}
}     > a=(x/foo y/bar x/baz y/qux)
}     > echo ${a/#(^x)\/*} # ok
}     x/foo x/baz
}     > echo ${a/#^x\/*} # wtf
}     /foo /baz
} 
} what's happening here?

You've forgotten that parameter expansion is a pattern match rather than
a filename glob and that slashes have no special significance in pattern
matching, so ^x\/* is ^(x\/*) despite the "higher precedence" mention.
 
} while i'm here: the whole workaround is cumbersome, you need to negate
} the pattern (might be difficult in some cases) and actually get as many
} items back as are in the input array (thus the nested parameter
} expansion, ${(j:,:)a/#(^x)\/*} produces "x/foo,,x/baz,").

You can work out why this happens if you read through the "rules for
substitution" in the Parameter Expansion section.  The short answer is
that you have to use a nested expansion to cause the array to be fully
normalized before you join its elements:

    ${(j:,:)${a/#(^x)\/*}}

If you're going to put that inside double quotes, additional gyrations
are required.

} i hoped zsh would have a direct way to expand only those items of an
} array that match a pattern, eg. ${@:/#sh\/*}.

Not sure what #sh\/* means (you can't start an extendedglob pattern with
the "#" repetition operator, though for some reason parameter expansion
doesn't gripe about it) but the (M) qualifier with the :# susbstition
should do what you want:

    ${(M)@:#pattern}



Messages sorted by: Reverse Date, Date, Thread, Author