Repeat shell command replacing a word

picasso with shells

Suppose you’ve typed a long command and you need to rerun it with a small modification. Say you need to replace foo with bar. Bash will let you do this with ^foo^bar^. And although you’re supposed to put the final caret on the end, it will let you get by without it.

    $ echo foo
    $ ^foo^bar

Great. Now suppose foo appears twice in a command.

    $ echo foo foo
    foo foo
    $ ^foo^bar
    bar foo

Surprise! Only the first foo gets replaced.

The way to fix this is to use !:gs/foo/bar/ to do a global replacement, i.e. to replace all instances of foo with bar. If you really only want to replace the first instance of foo then use the same command without the g.

    $ echo foo foo
    foo foo
    $ !:gs/foo/bar/
    bar bar
    $ !:s/foo/bar/
    bar foo

You can leave off the final slash and everything will still work.

What about zsh?

The zsh shell works a lot like bash, so much that I forget that I’m using zsh until something unexpected happens. “Oh yeah, I’m on my Mac [1]. This is zsh and not bash.”

So how do the examples above run under zsh? The simple substitution ^foo^bar to replace the first instance of foo with bar works just the same.

However, zsh offers another possibility, one that isn’t supported in bash. You can append :G to the substitution command with carets.

    % echo foo foo
    foo foo
    % ^foo^bar^:G
    bar bar

Here the final caret is critical. Without it you replace the first instance of foo with bar:G.

Event designators

These features are well documented, but it’s hard to find the documentation if you don’t know the buzzword to search for. If you try searching on “string replacement” and things like that, you’re likely to find other things that what you’re looking for.

For bash, the magic phrase is “event designator.” If you type man bash and scroll down to the section entitled Event Designators you’ll find everything mentioned here and more. On zsh the magic phrase is “history expansion.”

Related posts

[1] I use bash on Linux and zsh on Mac. When in Rome, do as the Romans do. Though I do remap a few keys in order to use muscle memory across platforms.

One thought on “Repeat shell command replacing a word

Comments are closed.