Bash history expansion
Apparently, histexpand (set -o histexpand) must be in effect for history expansion to work.
Using !
The exclamation mark can be used to refer to portions of one of the last commands executed.
!! is expanded to the last command. So
$ !!
repeats the last command.
A useful application for this construct is if
sudo was forgotten:
$ pacman -Syu
error: you cannot perform this operation unless you are root.
$ sudo !!
Repeat the most recent command that
starts with ls:
$ !ls
Repeat the most recent command that contains foo:
$ !?foo
:p does not execute the command but rather prints it:
$ !ls:p
!^ and !$
!^ is replaced with the first argument:
$ echo foo bar baz
foo bar baz
$ echo abc !^ def
abc foo def
Similarly, !$ is replaced with the last argument.
nth argument
Similar to !^ and !$, the nth argument can be referred to with !!:n:
$ echo one two three
one two three
$ echo !:3 !:2 !:1
three two one
!^ and !!:^ seem to be equivalent, as well as also !$ and !!:$.
All arguments are referred to with !!:*
Arguments n through m are referred to with !!:n-m
Arguments n and following are referred to with !!:n*
Searching for commands
!?text? searches for the last command that contained text and executes it.
Substituting elements in previous commands
!!s/text/replacement/ substitutes the first occurence of word:
$ !!:s/foo/bar/
gs/text/replacement/ substitutes every occurence of word (g=global).
:& reuses the last substitution:
!ls:&
^text^replacement^
^text^replacement^ replaces text in the last command with replacement.
$ ls -l tmp
$ ^-l^-la^
!n and !-n
As !! refers to the last command, !-n refers to the n-th last command and !n to command with number n (as printed with the history command).
As a convenience,
$PS1 can be set to something like
export PS1="\!$ " to always print the current history number which can be used in
!n.
Modifiers
The modifiers :h, :t, :r and :e can be used to select parts of a directory and/or file path:
#!/bin/sh
echo "PS1=
echo /path/to/a/file.extension
echo !-1:$:h # head, expands to /path/to/a
echo !-2:$:t # tail, expands to file.extension
echo !-3:$:r # remove extension, expands to /path/to/a/file
echo !-4:$:e # extension only, expands to .extension
echo !-5:$:t:r # Remove extension from tail, expands to file
" | bash -i # Use -i to start interactive shell
histappend
By default, bash overwrites the history when the session ends. With setting histappend (shopt -s histappend), bash appends the commands executed during a session when it ends.