[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. -JP]
The exclamation point (!
) is the C shell's
default (11.15)
history substitution
character.
(It's used in bash, too.)
This allows you to recall previously entered commands and re-execute
them without retyping.
The number of commands saved is up to you.
To set this number, put a line in your
shell setup file (2.2)
like this:
set history=40 ...C shell HISTSIZE=40 ...bash, ksh
This means that the C shell will save the last 40 commands. To list out these 40 commands use:
%history
To see just the last ten commands in csh or bash,
use history 10
.
In the C shell, you can also list out the commands in reverse with
history -r
.
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 used mostly to
select arguments from the command line in aliases (10.3).
Here they are:
!!
repeats the last command.
!:
repeats the last command.
This form is used if you want to add a
modifier (9.6)
like:
%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 . (7.2)
!! &
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 (25.3) 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 (9.6)
: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:
%cat fn fn1 fn2
... %more !:3
more fn2 ...
gives the third argument.
!:2-4
gives the second through the fourth argument, or 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, or 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 (26.4),
!^
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.
!*
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'
will pipe the output of
cat -v (25.7)
command through more.
The backslash (\
) has to be there to hide the history character,
!
,
until the alias is used-see article
10.3
for more information.
!:2*
gives the second through the last arguments:
%echo 1 2 3 4 5
1 2 3 4 5 %echo !:2*
echo 2 3 4 5 2 3 4 5
!:2-
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:
%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 (11.3, 11.5)
command.
In the case of:
%echo xxyyzzxx
xxyyzzxx %^xx^ab
echo abyyzzxx abyyzzxx
it replaced the 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 the colons (:
) [good when the word you're
trying to edit contains a slash-JP ].
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 (26.3). You must type the actual string you are looking for.
Also, the example above only replaces 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.
Or you could have done:
%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 that case, 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
.
[A "global" substitution works just once per word:
%echo xyzzy
xyzzy %!!:gs/y/p/
echo xpzzy xpzzy
The substitution above changed only the first y
. -TC ]
-