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

${name/pattern/repl} with negated pattern



this snippet in zshcontrib(1):

    for i in "$@"; do
        if [[ $i == sh/* ]]; then
            [[ -n $s ]] && s=$s,
            s=${s}$i
        fi
    done

can be reduced to

    s=${(j:,:)${@/#(^sh)\/*}}

i *thought*, based on the man page, that this would work as well:

    s=${(j:,:)${@/#^sh\/*}}

alas:

    > 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?

zshexpn(1) suggests parentheses are not required:

    ^x     (Requires EXTENDED_GLOB to be set.) Matches anything except
           the pattern x. This has a higher precedence than `/', so
           `^foo/bar' will search directories in `.' except `./foo' for
           a file named `bar'.

though this description of a ksh glob operator is suspicious:

    !(...) Match anything but the expression in parentheses.
           (Like `(^(...))'.)


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,").
i hoped zsh would have a direct way to expand only those items of an
array that match a pattern, eg. ${@:/#sh\/*}.

doable?

-- 
roman



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