I've since adopted another approach to this - using ![line-number]:p
This prints the statement and adds it to history but doesn't actually execute it. I then do up arrow and change it as desired.
I combine this with my hg
alias (alias hg='history | grep '
) to recall history commands based on some text.
Example:
$ hg checkout
17140 git checkout README.rdoc
17143 git checkout master
17201 git checkout README.rdoc
17204 git checkout master
17923 git checkout .bashrc
18151 git checkout v311
I use this in addition to ctrl-r (reverse history search) because sometimes I prefer to see an immediate list of all the possibilities for a given string rather than just the output on 1 line that ctrl-r shows. After hg [string]
I would then do ![line-number]search_string
as in the hg checkout
shown above.
Bash's command number is for display only.
First, some background from bashref
:
The command number and the history number are usually different: the
history number of a command is its position in the history list, which
may include commands restored from the history file (*note Bash History
Facilities::), while the command number is the position in the sequence
of commands executed during the current shell session.
Diving through the source, in parse.y
we see that '\#'
resolves to the global static variable current_command_number
:
case '#':
n = current_command_number;
/* If we have already incremented current_command_number (PS4,
${var@P}), compensate */
if (orig_string != ps0_prompt && orig_string != ps1_prompt && orig_string != ps2_prompt)
n--;
temp = itos (n);
goto add_string;
which only has one other use: in eval.c
, it's incremented upon running a command:
# ...
current_command_number++;
executing = 1;
stdin_redir = 0;
execute_command (current_command);
All that's kept is a number, not the actual command or even the equivalent history number. So, upon execution of each command, bash forgets what command associated with what command number, rendering the command number unusable for anything other than display and scroll reference.
Best Answer
To request that the command be printed rather than executed after history substitution, add the
:p
modifier, e.g.!42:p
. The resulting command will also be entered in the history, so you can press Up to edit it.If you have the
histverify
option set (shopt -s histverify
), you will always have the opportunity to edit the result of history substitutions.The
fc
builtin gives limited access to history expansion (no word designators), and lets you edit a previous command in an external editor.You can use
!prefix
to refer to the last command beginning withprefix
, and!?substring
to refer to the last command beginning withsubstring
. When you know what you're looking for, this can save a lot of time overhistory | less
.Another way to search through previous history is incremental search: press Ctrl+R and start entering a substring of what you're looking for. Press Ctrl+R to go to the previous occurence of the search string so far and Ctrl+S if you've gone too far. Most keys other than Ctrl+R, Ctrl+S, Backspace and ordinary characters terminate the incremental search and have their usual effect (e.g. arrow keys to move the cursor in the line you've reached, Enter to run the command).