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

Re: Substitute the last match of a pattern during parameters expansion.

On Sun, Sep 11, 2022 at 11:01 PM Lawrence Velázquez <larryv@xxxxxxx> wrote:
>         % foo=aXbXcXdXe
>         % print ${(*)foo/(#b)(*)X/$match[1]Y}

That works for the last match, but not for the Nth-from-last.  (It
also works only in zsh 5.9+, before that you need extendedglob set.)

You can do it more generally like this:

N=0  # Number of X to skip over when counting from the right
print -- ${(*)foo/%(#b)(*)X(*(X*)(#c$N))/$match[1]Y$match[2]}

Nested parens with #b and #c are a bit iffy though, e.g., the values
of $match[3] and beyond here are not what you might expect.

On Mon, Sep 12, 2022 at 11:07 PM Lawrence Velázquez <larryv@xxxxxxx> wrote:
> Your use case could theoretically be satisfied by an enhanced 'I'
> flag, so I don't think it deserves its own flag.
> On Tue, Sep 13, 2022, at 12:19 AM, Michele Venturi wrote:
> > How do you extend the I flag?
> I don't know.  I am not familiar with the code base.

Unfortunately this is non-trivial, because the value of the parameter
is scanned+replaced left-to-right and we don't know how many matches
there will be, to count backward.

If you want to simulate a negative 'I' flag, one way is to use an
array, splitting and joining on the substring to replace:

print -- ${(j:X:)z[1,N-1]}Y${(j:X:)z[N,-1]}

Which you can write as a single substitution if you want to obfuscate it:

print -- ${${(A)z::=${(@s:X:)foo}}:+${(j:X:)z[1,N-1]}Y${(j:X:)z[N,-1]}}

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