I'm not denying that the doc could be clearer - there should probably be a note in PARAMETER EXPANSION mentioning that history expansion modifiers can be used, instead of that note only being under HISTORY EXPANSION. But the clue that history is relevant is that, AFAICT, the only place the :s/old/new syntax is documented is in the HISTORY EXPANSION section.And of course you shouldn't have to know the history of the various features in order to use them. I phrased my earlier message as if it were about the origin of the modifier, which was poor wording on my part. The fact is, history expansion and parameter expansion are still separate systems within the shell that work differently from each other, which is why they have different sections in zshexpn. You can apply history expansion modifiers to parameter expansion, but it still has its own rules. So you'll be surprised less often if you know which system a given syntax is part of, and in general the modifiers signalled by a colon followed by a letter are all history expansion.On Tue, Jul 15, 2025 at 1:28 PM Vin Shelton <ethersoft@xxxxxxxxx> wrote:Thanks. As a user, I don't care how it originated, I care about how to use it. There was no ! in my question, so I didn't look in the history section of the manual.- VinOn Tue, Jul 15, 2025 at 1:12 PM Mark J. Reed <markjreed@xxxxxxxxx> wrote:History expansion is the stuff you can do with ! to retrieve values from history and modify them in various ways. Those modifiers are so useful that Zsh has added them to its parameter expansion. Doing a search and replace with :s/old/new/ is an example of a modifier that originated on the history side of things, as are most of the ones that involve a colon followed by a letter.
But the history expansion takes place in a different phase of evaluation and doesn't expand any nested parameter values, which is why your attempt didn't work - the value of SCMROOT doesn't contain the literal string "$HOME", so nothing is changed.For general search and replace, parameter expansion has its own substitution syntax - ${param/old/new} will replace only the first instance of "old" in the string, while $[param//old/new} will replace all of them. Unlike with :s, you can't change the delimiter and so have to escape any literal slashes in either the search or replacement values. But any nested parameters will be expanded (and slashes in the expanded value taken literally), so your attempt would work.However, if all you want to do is remove stuff from the beginning or end of a parameter value, there's targeted syntax for that, which Peter has supplied. In general, ${param#prefix} will remove stuff from the beginning of the string, and ${param%suffix} will remove stuff from the end. The stuff to remove can be specified via a wildcard pattern (not a regex, but a file glob), in which case a single # or % will remove the shortest thing that matches while a double ## or %% will remove the longest.On Tue, Jul 15, 2025 at 11:13 AM Vin Shelton <ethersoft@xxxxxxxxx> wrote:Although I see history mentioned in the zshexpn manpage, I don't know what my example has to do with history.On Tue, Jul 15, 2025 at 11:01 AM Eric Cook <llua@xxxxxxx> wrote:On 7/15/25 10:44 AM, Vin Shelton wrote:
> I don't understand the order of parameter expansion. Consider the following example:
>
> zsh -f
> export HOME=/home/acs
> smaug% export SCMROOT=/home/acs/scmroot
> smaug% echo ${SCMROOT:s-$HOME/--}
>
> This yields /home/acs/scmroot", but I expected "scmroot".
> TIA,
> Vin Shelton
>
The history modifier doesn't create a new context where the parameter expansion code recurses and resolves any parameters within it's operands.
It is searching for the literal string $HOME.
--Whoa, I'm just surprised at how accurate that description of me really is:some old cowboy guy that used to shoot movies at Spahn Ranch--Mark J. Reed <markjreed@xxxxxxxxx>--Whoa, I'm just surprised at how accurate that description of me really is:some old cowboy guy that used to shoot movies at Spahn Ranch--Mark J. Reed <markjreed@xxxxxxxxx>