Under Construction

Access to Parts of a Command from History

In many cases you do not need a complete command from the history, but only a part of the command, e.g. a longer argument. The shell generally breaks input into words. The first word is the command to be executed and all other words are the so-called arguments for the command. Words are separated from each other by spaces. You can access individual words or arguments from previous commands via the bash history mechanism. To do this, a colon “:” is added to the end of the event identifier discussed in the previous subsection, followed by the specification of the number of the desired word. Words are numbered starting with zero. I.e. word 0 is the command itself and word 1 is the first argument of the command.

We start with the following history:

[user01@aixe01 ~]$ history
    1  ls -l /usr
    2  vi sample.txt
    3  ls -l sample.txt
    4  cat sample.txt
    5  cp sample.txt working_copy_of_sample.txt
    6  cat sample.txt
    7  cat start.ksh
    8  cat stop.ksh
    9  history
[user01@aixe01 ~]$

The file working_copy_of_sample.txt shall be edited with vi. We can of course type in the complete command:

[user01@aixe01 ~]$ vi working_copy_of_sample.txt

That’s 29 characters, including the newline at the end!

History expansion is shorter. The desired file appears in the command with the number 5 (“cp sample.txt working_copy_of_sample.txt“) as the second argument (word with the number 2). I.e. the history mechanism of bash would replace (and execute) “!5” with the complete command. However, if you add a colon “:” and the number of the word (here 2), as described above, you get “!5:2“. This is replaced by “working_copy_of_sample.txt” by bash‘s history mechanism. This means that instead of specifying the 29 characters for “vi working_copy_of_sample.txt“, you can instead write “vi !5:2“:

[user01@aixe01 ~]$ vi !5:2
vi working_copy_of_sample.txt

That’s only 8 characters (including newline)!

Since the command with the number 5 was the last command that begins with “cp“, you could of course also use “!cp:2“. This is one more character, but has the advantage that you don’t have to remember the number of the command.

Alternatively, you can also search for the last command that contains the character string “working” or “work” (or just “w“) and then access the second argument:

[user01@aixe01 ~]$ vi !?work?:2
vi working_copy_of_sample.txt

Or even shorter:

[user01@aixe01 ~]$ vi !?w?:2
vi working_copy_of_sample.txt

In all these cases, however, you have to specify the number for the correct argument (here the “2” in each case). Instead of the number, you can also enter the percent sign “%” after the colon, but only if question marks “?” were used in the event identifier. The percent sign then refers to the argument in which the specified character string was found. It doesn’t matter if it was the first or second word, or in any other position:

[user01@aixe01 ~]$ vi !?w?:%
vi working_copy_of_sample.txt

You then only have to know that the required word occurred recently as an argument in some command and can then refer to this word!

In addition to specifying the number of the word and the percent sign for the word that matched the search string, there are also abbreviations for the first and last word (argument):

    • ^   The first word (argument), this is identical to using “1”.
    • $   The last word (argument).

So far we have always referred to exactly one word. But you can also specify ranges of words. For example, if recently the following echo command has been used:

[user01@aixe01 ~]$ echo A B C D E F
A B C D E F
[user01@aixe01 ~]$

then one can refer to the words two through four by using the range “2-4”:

[user01@aixe01 ~]$ echo !echo:2-4
echo B C D
B C D
[user01@aixe01 ~]$

If you need all arguments (all words after the command), then there is the obvious abbreviation “*”:

[user01@aixe01 ~]$ banner !echo:*
banner A B C D E F
   #
  # #
#   #
#     #
#######
#     #
#     #

######
#     #
#     #
######
#     #
#     #
######

#####
#     #
#
#
#
#     #
#####

######
#     #
#     #
#     #
#     #
#     #
######

#######
#
#
#####
#
#
#######

#######
#
#
#####
#
#
#

[user01@aixe01 ~]$

Below is the full list of possible word specifiers:

    • 0   The zeroth word, i.e. the command name.
    • n   The nth word.
    • ^   The first argument, this is word 1.
    • $   The last argument
    • % The word that matched the search string “?string?“.
    • n-m   The range of words n to m (inclusive)
    • -m   Abbreviation for 0-m.
    • *   All arguments, i.e. all words except the word 0. Abbreviation for 1-$
    • n*   Abbreviation for n-$
    • n-   All words from n, except the last word.