Greetings mail-forum-merge,
------------------------------------------------------------------------------
Recent content - 1 new post
------------------------------------------------------------------------------
1. Bash Command Line Editting and History
Published Book page by john
[ http://kwlug.org/node/766 ]
In Bash the text on the command line can be edited in place using cursor
keys, backspace and delete. Bash also retains a history of entered
commands so you can easily reuse or edit previous commands and use all
or part of previous command lines in new commands. The simplest way of
accessing history is using the up and down arrow key, then using left,
right, backspace and delete to edit the line.
This normally works quite well if you are using a decent terminal
emulation. This is true for the Linux console and an X-Windows terminal
emulator, but you may have problems if you are trying to use a Windows
terminal emulation program or a clunky old serial terminal. I'm not
going to to into these at this time because not may clunky old terminals
were spared from landfill and if you're using Windows you can just
download Putty and get a decent emulator.
Editing Keys
The keys for editing are simple. If all is set correctly you can use
your cursor keys. Up goes to the previous issued command, down to the
next command. Left and Right move between characters in the displayed
command so that you can selectively edit characters. Delete and
Backspace should work as expected as should Home and End.
In fact it's so simple that mentioning this could be insulting, so I'm
sorry.
But if in fact you don't have cursor keys working you can use the Ctrl-P
for previous issued command and Ctrl-N for the next command. Ctrl-F and
Ctrl-B stand in for cursor right and left. Ctrl-H should work for
backspace and delete.
If you don't like these you can map your own keys using the bind
built-in command.
Displaying History
You can display the entire history of lines you've issued using the
history built-in command:
history
This will show a enumerated list of all the previous commands.
You can also selectively list history using the fc command:
fc -l -20
The above shows the last 20 commands.
Searching history
There are several ways to search through history to find certain
commands. The easiest way to search history is using the
reverse-search-history function. To access it press Ctrl-R, you will be
prompted for a search string, enter a search string, either part of a
command or an argument. The most recent matching entry will
automatically appear as you type. If the most recent isn't what you want
you can press Ctrl-R again to select the next most recent matching
entry. When you see the command you want use cursor keys to edit the
entry if you like or press Enter to execute the command. So what if you
go too far and want to forward through matching entries. Well that's
complicated. There is a simple keystroke that does this, Ctrl-S, but if
you try it won't work. So we can find out why it doesn't work or we can
change it to another keystroke. That's right, it's all configurable.
Ctrl-S Problem
Ctrl-S happens to be a hold-over from the days of low-speed serial
communications. It was a special code that would tell the remote end of
the serial line to stop sending characters. It was a way to prevent lost
characters. It was implemented in the tty serial driver so it's
essentially the kernel that "eats" the code. Today, we have hardware
consoles and network connections so we can do away with this character.
Now if you ever access your system from an old serial cable or telephone
modem (and I don't mean a DSL or cable modem) you might want to
reconsider this change.
To prevent Ctrl-S from being eaten by the tty driver run this command:
stty stop ''
If you want this to be a permanent change you will have to add this to
your .bashrc file.
After that change the tty driver will pass the Ctrl-S to the process and
your forward-history-search function will work.
Another way to deal with this is to bind a new key to the function. We
use the bind command along with the official name of the function
forward-history-search. In this example we'll bind Ctrl-B (cursor left)
to the function since we can use cursor keys to move the cursor.
bind '\C-b':forward-search-history
If we want to make this permanent we would need to add it to your
.bashrc file.
Now you can use Ctrl-B to search forwards through history.
History Expansion
This next section is pretty intense so if you think you have all you
need to use Bash history ignore this section. If you want to become a
command line king you'll need to keep reading there are some real time
savers here if you're willing to commit some of these keystrokes to
memory.
Another way to use history is through expansion. This means use special
codes to insert previous commands, or parts of them, into the current
line and optionally to change them during substitution.
The simplest form of history expansion is an Event Designator. It starts
with an exclamation mark (!) and has many forms:
Event Designator
Example
Description
!!
!!
Substitute the last command line in full
!n
!123
Substitute command line 123 from history. The number comes from the
listing from either the histOry or fc command.
!-n
!-3
Substitute the third last command line from history.
!string
!vi
Substitute the last command that begins with vi.
!?string?
!?recipe?
Substitute the last command line which contains the word .
!#
!#
Substitute the current command line so far.
^string1^string2^
^needle^haystack^
Substitute the previous command but replace needle with haystack
We can use one of the substitutions anywhere in a command line.
Typically it's used to re-issue commands and often they are used on a
blank line:
!!
This would simply re-run the previous command. This doesn't sound as
easy as simply pressing Up cursor and Enter. But consider that you want
to re-issue a line from a long time ago, but you know it was the last
time that command was used. It could be really handy to re-issue the
last of a specific command:
!man
That would run the last man command. Be careful though it will also
match a command called "mangle" it matches beginning of line. It's
usually pretty safe though since you would have had to issue a "mangle"
command after the last man command.
If we want to echo the previous line it would be simple:
echo !!
The result of the above would be that the previous command would be
displayed on the screen.
This also shows one way to test history expansion, by echoing the
history you are trying to substitute. Another way is to press Esc ^.
This key sequence will expand the history on the command line without
executing it.
A more useful example of expansion is:
logger "Finished: !!"
sudo tail /var/log/messages
The above would log the previous line to the system logs. The sudo tail
command runs tail as root and lists the last few lines of the
/var/log/messages file. You should see your last command listed in the
log file.
Advanced Substitition
We can also grab just a portion of a previous command line, this syntax
is called Word Designators and allows one to extract words from a
previous command you and substituting them into the current command.
This is really useful if you are working on large arguments, whether
that is a command name or file name, or a list of complex arguments.
Word designators always follow an Event Designator (see above) but are
separated from them with a colon (:). They apply to the command line
selected by the Event Designator. So if we wanted to pull words from the
last line we would start with !!: and add one of the following word
designators:
Word Designator
Example
Description
0
!!:0
Substitute word 0 from the last command line (i.e. the command from the
previous line)
n
!!:2
Subtitute word 2 from the last command line
$
!!:$
Substitute the last argument from the last command line
%
!?hel?:%
Substitute the most recent word found in history that contains the text
hel.This really works by substituting the last word searched for with
!?string?. The search doesn't need to be on the same line. In other
words once you've searched once with !?string? you can use !% over and
over and it will give the same result.
n-m
!!:2-4
Sustitute words n through m. You can abbreviate 0-n to -n.
*
!!:*
Substitute arguments 1 and on.
n*
Substitute arguments n and on.
n-
Substitute arguments n to the second last
There are some interesting uses of this. Let's say you used a very long
file name that has a unique name, recipe. To verify you could search for
this name without executing the command by putting the substitution
after an echo command:
# Sometime before you ran
# vi /home/john/documents/recipes/southwest/quacamole_dip.txt
#
echo !?recipe?
Once found the !% will now work until the next search. That means you
can use the argument easily in another command:
lp !%
That command would result in this string lp
/home/john/documents/recipies/southwest/quacamole_dip.txt and would
print the file only you typed a lot less.
You can also re-issue the same command arguments over and over. Lets say
you just looked into a file and decide it's in the wrong directory:
vi /home/john/documents/recipes/southwest/poutine.txt
mv !$ /home/john/documents/recipes/canadian
As you can see !$ and !% are shortforms for !!:$ and !!:%.
Modifiers
We can also apply a modifier to the selected history. This is handy for
doing slight alterations to substitute text.
Modifier
Example
Description
h
!:1:h
Substitute only the head of the file path. i.e. remove the trailing
element of the path. E.g. /home/john/.bashrc becomes /home/john
t
!:1:t
Substitute only the tail of the file path. i.e. remove all but the last
element of the path. E.g. /home/john/.bashrc becomes .bashrc
r
!:1:r
Remove the trailling file suffix. i.e. remove everthing after the last
dot in the file name. e.g. /home/john/resume.txt becomes
/home/john/resume
e
!:1:e
Leave only the trailing file suffix. e.g. /home/john/resume.txt becomes
.txt
p
!:p
Substitute but don't execute, only print.
q
!*:q
Quote the substituted words with single quotes to avoid expansion. To
see this in effect try:
echo $PATH $PATH
echo !*:q
x
!*:x
Quote the substituted words at word breaks (spaces, newlines). To see
this in effect try:
echo $PATH $PATH
echo !*:x
s/old/new/
!?poutine?:s/southwest/canadian/
Substitute new for the first occurrence of old in the event
line. Any delimiter can be used in place of /. The
final
delimiter is optional if it is the last character of the
event
line. The delimiter may be quoted in old and new with a
single
backslash. If & appears in new, it is replaced by old.
A single backslash will quote the &. If old is null, it is set to
the last old substituted, or, if no previous history
substitutions took place, the last string in a !?string[?] search.
&
!-5:&
Repeat the last substitution. (presumably on another line)
g
!?images?:gs/.jpeg/.jpg/
Cause changes to be applied over the entire event line. This is
used in conjunction with ‘:s’ (e.g.,
‘:gs/old/new/’) or ‘:&’.
If used with ‘:s’, any delimiter can be used in place
of /, and
the final delimiter is optional if it is the last
character of
the event line. An a may be used as a synonym for g.
G
!?images?:Gs/mexico/Mexico/
Apply the following ‘s’ modifier once to each word in the event
line.
--
This is an automatic e-mail from KWLUG - The Kitchener Waterloo Linux
User Group.
To stop receiving these e-mails, change your notification preferences at
http://kwlug.org/user/28/notify