zsh: Bang History Word Substitution
Yes, your job is repetitive, and typing a series of
git commit and
git push doesn't help.
When I need to redo something I've already done, usually I just hit
the up-arrow key if the shell command was recent (like one or two
commands ago), or type
Control-R and followed by some keyword on the
command line. Sure, this approach often requires multiple
keystrokes until I would get to the right command, but this feature
has served me well for thousands of years.
This is why I never bothered with the bang history substitution
!43 to repeat the 43rd command entry. But I just
learned about word substitutions while perusing the
Let's assume you've done the following commands:
$ git add src/main/resources/nav/unified/templates/nav.handlebars
$ git commit -m "Fixed bug #249, and well, you know. . ."
$ git push origin HEAD:refs/publish/development
Now, with the next bug on your queue, you want to edit that same
file, but copying/pasting is so 1984. Type this:
$ echo !-4:2
You can now either hit
Tab, and that filename shows
up after the
echo command. Pretty slick.
How does it work? Well the
-4 says, grab the 4th previous entry††Yes, it is the fourth since what you are typing now is always
:2 part says, grab the second argument to the command, in this
case, the filename.
But who wants to count the history? Try this on for size:
$ echo !git:3
This echoes the third argument to the last
git command you typed, in
my particular example, that would be the remote branch name.
But how to get that filename four lines back without counting? How about:
$ echo !?add?:$
This looks through the history until it finds an
add parameter (in
this case, attached to the
git command), and then brings back the
final argument (that's what the
:$ tells it).
Here is a snippet from the Zshell man page (
zshexpn) for all of the
0 The first input word (command).
n The nth argument.
ˆ The first argument. That is, 1.
$ The last argument.
% The word matched by (the most recent)
x−y A range of words;
x defaults to
* All the arguments, or a null value if there are none.
x* but omitting word
Note that a
% word designator works only when used in one of
!?str?:%, and only when used after a
(possibly in an earlier command). Anything else results in an error,
although the error may not be the most obvious one.
Tell others about this article: