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

Re: Belaboring substitution syntax



On Tue, Nov 15, 2022 at 6:18 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
>
> I sorta get that '[@]' is saying: "process this array line by line" thus preserving array indexes.  I'm not sure about the quotes.

This follows the same rules as $@.  If you write "${array[@]}" with
the quotes, you get each element of the array separately quoted.  This
often doesn't matter in zsh but always matters in other shells or when
SH_WORD_SPLIT is enabled in zsh.

BTW you need to stop thinking of these as "lines" -- line breaks have
nothing to do with it.

Conversely if you write "${array}" or ${array[*]}" either one with the
quotes, you get the entire array joined into a single string.

> and sometimes the quotes seem to protect stuff from expansion or interpretation:

Quotes ALWAYS protect SOMETHING from expansion or interpretation,
unless you start throwing other things in there such as eval.  WHAT is
protected differs:  Double quotes allow ${param} and $(process) and
$((math)) replacements but protect syntax tokens and glob patterns and
whitespace; single quotes protect pretty much everything.

> In my case, leaving the quotes out doesn't *seem* to matter but I know it would bite me eventually.  When would it bite me?

In the specific example in this thread, zsh's default array behavior
(no_SH_WORD_SPLIT) is sufficient, but if you later enclose that or a
similar construct in a deeper context, yes, you might be bitten.

> Do we not have an operator that says (in English): If string A is a substring of B, then return B, else return nothing.

Your trouble is the definition of "nothing."  ${B:#*A*} does that, but
in your example here, you don't actually want "nothing", you want "the
empty string" which is still something.

In fact the example in question is "if A is NOT a substring of B then
return B, else return the empty string."

So we have this:
Do a replacement on every element of $cc is  ${cc[@]/...}
Replacement must start at beginning of element ${cc[@]/#...}
Replacement must also end at end of element ${cc[@]/#%...}
Use $zsh_case as a pattern is $~zsh_case
Match that pattern anywhere with $filter is *$~zsh_case${filter}*
Match NOT that whole pattern is ^*$~zsh_case${filter}*
Put it all together:  ${cc[@]/#%^*$~zsh_case${filter}*
Replace all that with the empty string is just close the brace
${cc[@]/#%^*$~zsh_case${filter}*}
... and then the double-quotes for safety.

About the only thing your magical operator could remove is putting
*...* around the pattern to mean "is a substring".




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