Although most of the examples here use echo to demonstrate clearly just what is going on, you'll normally use history with other Unix commands.
The exclamation point (!) is the default (Section 30.15) history substitution character. This allows you to recall previously entered commands and re-execute them without retyping. To use the ! in a command line, you have several choices. Some of the following examples are more of a headache than they may be worth, but they are also used to select arguments from the command line in aliases (Section 29.3):
!: repeats the last command. This form is used if you want to add a modifier (Section 28.5) like the following:
% echo xy xy % !:s/xy/yx echo yx yx
The second ! was left out.
!so repeats the last command that starts with so.
!?fn? repeats the last command that has fn anywhere in it. The string could be found in an argument or in the command name. This is opposed to !fn, in which !fn must be in a command name. (The last ? need not be there. Thus !?fn means the same thing.)
!34 executes command number 34. You can find the appropriate history number when you list your history using the history command, or by putting the history number in your prompt (Section 4.3).
!! & adds an ampersand (&) to the end of the last command, which executes it and places it into the background. You can add anything to the end of a previous command. For example:
% cat -v foo ... % !! | more cat -v foo | more ...
In this case the shell will repeat the command to be executed and run it, adding the pipe through the more pager. Another common usage is:
% cat -v foo ... % !! > out cat -v foo > out
which returns the command but redirects the output into a file.
!:0 selects only the command name, rather than the entire command line.
% /usr/bin/grep Ah fn1 ... % !:0 Bh fn2 /usr/bin/grep Bh fn2
Note that as an operator (Section 28.5,), :0 can be appended to these history substitutions as well. For example, !!:0 will give the last command name, and a colon followed by any number will give the corresponding argument. For example, !:3 gives the third argument:
% cat fn fn1 fn2 ... % more !:3 more fn2 ...
!:2-4 gives the second through the fourth argument; use any numbers you choose:
% echo 1 2 3 4 5 1 2 3 4 5 % echo !:2-4 echo 2 3 4 2 3 4
!:-3 gives zero through the third argument; use any number you wish:
% echo 1 2 3 4 1 2 3 4 % echo !:-3 echo echo 1 2 3 echo 1 2 3
!^ gives the first argument of the previous command. This is the same as !:1. Remember that just as the ^ (caret) is the beginning-of-line anchor in regular expressions (Section 32.5), !^ gives the beginning history argument.
% cat fn fn1 fn2 ... % more !^ more fn ...
!$ gives the last argument of the last command. In the same way that $ (dollar sign) is the end-of-line anchor in regular expressions, !$ gives the ending history argument. Thus:
% cat fn ... % more !$ more fn ...
The new command (more) is given the last argument of the previous command. This is also handy for pulling the last argument from earlier commands, which is typically a filename. To get the last argument from the previous vi command, for example, you'd use !vi:$. So you could type lpr !vi:$ to print the last file you edited with vi.
!*is shorthand for the first through the last argument. This is used a lot in aliases:
% echo 1 2 3 4 5 1 2 3 4 5 % echo !* echo 1 2 3 4 5 1 2 3 4 5
In an alias:
alias vcat 'cat -v \!* | more'
This alias will pipe the output of cat -v (Section 12.4) command through more. The backslash (\) has to be there to hide the history character, !, until the alias is used -- see Section 29.3 for more information.
!:2* gives the second through the last arguments; use any number you wish:
% echo 1 2 3 4 5 1 2 3 4 5 % echo !:2* echo 2 3 4 5 2 3 4 5
!:2- is like 2* but the last argument is dropped:
% echo 1 2 3 4 5 1 2 3 4 5 % echo !:2- echo 2 3 4 2 3 4
!?fn?% gives the first word found that has fn in it:
% sort fn1 fn2 fn3 ... % echo !?fn?% echo fn1 fn1
That found the fn in fn1. You can get wilder with:
% echo 1 2 3 4 5 1 2 3 4 5 % echo !?ec?^ echo 1 1
That selected the command that had ec in it, and the caret (^) said to give the first argument of that command. You can also do something like this:
% echo fn fn1 fn2 fn fn1 fn2 % echo !?fn1?^ !$ echo fn fn2 fn fn2
That cryptic command told the shell to look for a command that had fn1 in it (!?fn1?), and gave the first argument of that command (^). Then it gave the last argument (!$).
^xy^yx is the shorthand substitution (Section 30.3, Section 30.5) command. In the case of:
% echo xxyyzzxx xxyyzzxx % ^xx^ab echo abyyzzxx abyyzzxx
it replaced the first set of characters xx with ab. This makes editing the previous command much easier.
!!:s/xx/ab/ is doing the same thing as the previous example, but it is using the substitute command instead of the ^. This works for any previous command, as in:
% more afile bfile ... % echo xy xy % !m:s/b/c/ more afile cfile
You do not have to use the slashes (/); any character can act as a delimiter.
% !!:s:xy:yx
There we used colons (:), good when the characters you're trying to edit contain a slash. If you want to add more to the replacement, use & to "replay it" and then add on whatever you like:
% echo xy xy % !!:s/xy/&yx echo xyyx xyyx
The & in the replacement part said to give what the search part found, which was the xy characters.
The search part, or left side, cannot include metacharacters (Section 32.3). You must type the actual string you are looking for.
Also, the example above replaces only the first occurrence of xy. To replace them all, use g:
% echo xy xy xy xy xy xy xy xy % !!:s/xy/yx/ echo yx xy xy xy yx xy xy xy % !!:gs/xy/yx/ echo yx yx yx yx yx yx yx yx
The g command in this case meant "do all the xy s." And oddly enough, the g has to come before the s command. This may seem odd to those of you familiar with vi, so be careful.
Or you could have done this:
% echo xy xy xy xy xy xy xy xy % !!:s/xy/yx/ echo yx xy xy xy yx xy xy xy % !!:g& echo yx yx yx yx yx yx yx yx
In this example, we told the shell to globally (:g) replace every matched string from the last command with the last substitution (&). Without the g command, the shells would have replaced just one more xy with yx.
-- DR
Copyright © 2003 O'Reilly & Associates. All rights reserved.