vi
and ex
†
vi
/ ex
.
vi
has three modes
vi
starts in command mode where you can issue commands to move the cursor, cut, copy or modify text. i
, a
change to insert mode.
This is the biggest problem that most people have with vi
. Pressing the same key has different effects depending on the mode.
For example, in command mode pressing i
changes to insert mode. At this point pressing i
inserts the character i
into the file.
Typing a :
(colon) puts you in ex mode where you can use
powerful ex commands which frequently operate on a range of lines like
g
,
s
,
v
,
!
etc.
Enter the ex command :set showmode
to have vi
display -- INSERT --
on the bottom line of the display when in insert mode
Ï is any of:
ex
━━━━━━━━━━━━━━━━━━━┐ command ┃ example: %s/x/y/g ┃ ┃ vi commands ━━>━━━━━━━━━━━━⊣ x,w,$ … ⎮ ^ Ï enter characters ␛ ━━━━━━┐ ⎮ insert ⎮ ⎮ ⎮ mode ⎮ ⎮ ⎮ ⎮ ⎮ <━━━━━━━━━━━━<━━━━━━━━━━━━━━━━━━━━━┘ ⎮ └━━━━━━━━━━━━━━━━━━━━<━━━━━━━━━━━━━━━━━━━━┘
i,I
(insert) a,A
(append)
c
(change) o,O
(open)
|
[n] operator
Examples | |||||||||||
5x | |||||||||||
5rx | 5$ |
Editing commands c
, d
, y
have the form
[n] operator [m] object
An object is a character, word, line, sentence etc.
c begin a change
| d begin a delete
| y begin a yank
|
cc
, dd
, yy
operate on the current line, i.e. copying, deleting or yanking the current line.
If both n and m are specified the effect is n * m, that is n multiplied by m.
Examples | ||||||||||||||||||||||||
cw |
Commands are not echoed except the following which are echoed on the status line.
/ | search forward | ? | search backward | ||||||
: | invoke an ex command | ||||||||
! | invoke a OS command that takes as its input, an object in the buffer, and replaces it with output from the command |
The above commands are completed by pressing enter.
A buffer refers to the file as it's kept in memory.
<
, >
, and !
can also be combined with
a movement command like c
, d
, and y
Examples | |||||
>> |
B
stands for <control-B> a
or i
,
press [esc]
for the execution to occur count times. See example in
Part I/a.n | a | append after cursor | n | A | append at end-of-line (same as $a) | ^A | unused | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | b | back up a word | n | B | back up a WORD | n | ^B | scroll up a screen | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | c | begin a change (combine with movement command) | n | C | change line from cursor to end-of-line (same as c$) | ^C | abort current ex command in insert mode : end insert mode | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | d | begin a delete (combine with movement command) | n | D | delete from cursor to end-of-line (same as d$) | n | ^D | scroll down a half screen in insert mode : back up one shiftwidth | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | e | goto end-of-word | n | E | goto end-of-WORD | n | ^E | scroll a more line at bottom of screen | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | f | forward to next typed character | n | F | backward to next typed character | n | ^F | scroll down a screen | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
g | unused† | n | G | goto line n; default is end-of-file | ^G | print file info on status line (bottom of screen) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | h | cursor left | n | H | goto Home of screen or n lines from top of screen | n | ^H | cursor left in insert mode : backspace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | i | insert before cursor | n | I | insert at beginning-of-line (same as _i) | ^I | unused in insert mode : tab key | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | j | cursor down | n | J | join current line with next | n | ^J | cursor down in insert mode : same as enter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | k | cursor up | K | unused | ^K | unused | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | l | cursor right (hjkl) | n | L | goto Last line of screen n will place cursor that many lines from bottom of screen | ^ L | redraw screen, usually | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
m | mark current cursor position with character typed (a-z) | M | goto middle of screen | n | ^M | goto first character on next line in insert mode : same as enter key | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | next search match | N | Next search match BUT in opposite direction | n | ^N | cursor down | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | O | open a new line above the cursor | n | o | open a new line below the cursor | ^O | unused | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | p | put yanked or deleted text after or below cursor | n | P | put yanked or deleted text before or above cursor | n | ^P | cursor up | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
q | unused | Q | quit vi, invoke ex (not very useful) return with vi | ^Q | unused (some terminals, stop data flow) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | r | change character under cursor to character typed | n | R | replace characters (overwrite mode) | ^R | redraw screen, usually | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | s | substitute characters under cursor to ones typed | n | S | substitute entire line | ^S | unused (on some terminals, resume data flow) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | t | forward to before next character typed | n | T | backward to after next character typed | ^T | goto previous tag in insert mode : move right one shiftwidth | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
u | undo last change | U | restore current line | n | ^U | scroll screen up a half screen in insert mode : delete back to start of insert (depends on terminal settings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
v | unused | V | unused | ^V | unused in insert mode : quote next character | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | w | forward a word | n | W | forward a WORD | ^W | unused in insert mode : back up to beginning of word (depends on terminal settings) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | x | delete character under cursor | n | n | delete back a character | ^X | unused | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
n | y | begin a yank (combine with movement command) | n | Y | yank current line (same as yy ) (map it to y$ to be consistent with D and C )
| n | ^Y | show more lines at top of screen i.e. scroll back | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
z enter reposition line with cursor to top of screen
| | z . reposition line with cursor to middle of screen
| | z - reposition line with cursor to bottom of screen
| | ZZ exit vi, write changes
| | ^ | Z suspend vi on systems that have job control (depends on terminal settings)
| | ^ | @ unused
| | [esc] |
vi commands can be remapped.
Use :map
to list the current ones.
Here are some useful ones.
( note ^M
is the control sequence for [enter])
map ^N :n^M ^N
finds the next match and without pressing [enter]
map ^P :rew^M ^P qq begin recording
map Y y$ Y qq
map g 1Gi g goes line 1 for inserting
|
Control characters will have to be quoted with ^V
, that is
<control-V>
Alphabetical list of commans shows unused
addresses i.e. line ranges 0 (zero) beginning of file
| $ end-of-file
| % stands for filename, | i.e. the entire file 1,$ all lines in file
| . current line
| / pattern/ forward to line matching pattern
| .,/ pattern/ forward to line matching pattern
| .,/table/ |
abbreviate | move | tag |
append | next | unabbreviate |
args | number # | undo |
change | open | unmap |
chdir chd | preserve | version |
copy t | visual | |
delete | put | write |
edit | quit | xit |
file | read | yank |
global | recover | (window) z |
insert | rewind | (escape to OS) ! |
join | set | (lshift) < |
list | shell | (rshift) > |
map | source | (line number) = |
mark k | substitute s & ~ | (execute buffer) * @ |
range aka address[,address] specifies the optional range of affected lines.
examples:
1,3s/A/a/
affects lines 1 through 3, substituting A for a
.,$d
from this line to the ending line delete
The default for address is the current line,
except for g, g! , v, w; these the default is the entire file.
range
s ubstitute |
substitute pattern with replacement . count number of lines to operate on.options : c prompt for confirmation g all occurances on line p print last line on which substitution was made
If examples:All lines, substitutehello or Hello with hi , all ocurrences :%s/[hH]ello/Hi/g
Upcase unix on next 10 lines
turn the first letter of all words to uppercase
Substitute all occurances of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
u ndo | undo changes made by last editing command. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
x it | exit file. save changes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
address a ppend[!]text . | append text at address . ! switches autoindent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
address i nsert[!]text . | insert text at line before address. ! switches autoindent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
range c hange[!]text . | replace lines with text. ! switches autoindent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
range co py destination copy lines from address to destination . | example: copy lines 1 to to 10 to below line 50 :1,10co50
range | t destination
range | d elete [buffer][count]
delete lines in range , if buffer is specified save lines to buffer.
count specifies the number of lines to delete starting with range . | examples: :/include/,/main/d delete lines between include and main inclusive :/include/+,/main/-d as above but not including include nor main :3d delete line 3 :d3 delete 3 lines starting with current :.,$d a delete to end-of-file from current line into buffer a :d a3 delete next three lines starting with current into buffer a
| e dit[!] [+n] [file]
begin editing file. | ! will discard changes to current file. n specifies line to begin editing file (default 1). eg. :e file edit file :e # edit previous file
| f ile [filename]
change name of file to filename. | without argument print current filename. :f %.new appends .new to current filename, renaming file to file.new
range | g lobal [!]/pattern/[commands]
execute commands on lines that contain pattern, | if address is specified within the address range. ! execute on lines not containing pattern. default for commands is p rint . eg. :g/\#include/d delete all lines that have include directives :g!/\#define/p print lines that are not define statements :g/^\/\*/p print lines that start with /* comment :g/^^I*$/d delete empty lines as well as lines with only tabs or spaces :g/strcmp/d5 delete 5 lines, wherever strcmp occurs.
range | j oin[!][count]
join lines in specified range. | ! preserves white space. eg. :1,5j ! join lines 1 to 5, preserve white space
range | k [char]
synonymn for mark, | char can follow k with no intervening space. range | l ist[count]
print lines so that tabs show as ^I | and end-of-lines are marked with $.
| map [!] [char commands]
Define a keyboard macro for named char that is a synonymn for commands. | ! will create a mapping for input mode. With no arguments, print mapped keys. eg. :map ^N :n^M (to enter a control character type ^V followed by the control character)
| unm ap[!] char remove char from keyboard macros. ! remove macros for input mode.
| ab breviate string text
define string that when typed is translated to text. | if string text not specified, list abbreviations. abbreviations are usually put into your .exrc file examples: correct spelling mistakes !! :ab charcater character :ab teh the :ab hvae have :ab (shows all current abbreviations) |
The following can be used as addresses in ex, as well as in commands :g, :s, :v, and in the vi commands ?, and /
SPECIAL CHARACTERS | |||
. | any single character except newline | ||
* | 0 or more of the single atom immediately preceding | ||
^ | beginning-of-line if at start of expression | ||
$ | end-of-line if at end of expression | ||
[ ] | anything in [ ] character class | ||
[^] | anything not in [ ] | ||
\( \) [esc] | store pattern for later replay | ||
\< [esc] | following characters at beginning of word | ||
\> | preceding characters at end of word | ||
\ | escape following special character (ex:use \. to match a dot ) | ||
\n | reuse previous pattern, n is a number between 1 and 9 eg. \1
| ||
& | reuse previous search pattern | ||
~ | reuse previous replacement pattern | ||
\u | change character to upper case | \U | change characters to upper case |
\l | change character to lower case | \L | change characters to lower case |
\e | turn off previous \u or \l | \E | turn off previous \U or \L |
EXAMPLES | |
Perl | Perl |
^Perl | Perl at beginning-of-line |
Perl$ | Perl at end-of-line |
^Perl$ | Perl as the only word on line |
^$ | the empty line |
^..*$ | a line with at least one character |
.* | any string of characters including none |
^[ ^I]*$ | as above but line can also contain spaces and/or tabs(^I) |
[pP]erl | perl or Perl |
[aA][nN] | an, aN, An, AN |
p[aeiou]g | second letter is a vowel |
i[^aeiou]g | second letter is not a vowel |
p.g | second letter is anything |
^....$ | a line with exactly four characters |
^\. | any line beginning with a dot |
^\.[0-9a-z] | same with a lowercase letter or digit following |
^[^\.] | any line that does not begin with a dot |
;$ | line ending with a semicolon |
figs* | fig, figs, figss, figsss ... |
[a-z][a-z]* | one or more lowercase letters |
[a-zA-Z] | lower OR uppercase letter |
[^0-9a-zA-Z] | any symbol (not a letter or number) |
\<the | the, theater, then |
the\> | the, breathe |
\<the\> | the |
usefull operations for the entire file | ||||||||
:%s/\<./\u&/g | turn the first letter of all words to uppercase | |||||||
:%s/\<[a-z][!-~]*\>/\u&/g | ||||||||
:%s/\<[a-z]/\u&/g | ||||||||
:%s/.*/\L&/ | turn entire file to lowercase | |||||||
:%s/<<>>^>]*>//g | remove strings that start with a less than sign and end with a greater than sign (html tags) |
.( a what?? qq ), ^, &, $
must be preceded by a \ to make literal when magic is on. * must be preceded by a \ under certain circumstances qq which are:..... although it never hurts to precede it with a backslash whenever you mean a * not its regexp meaning. % and # should also be escaped as they mean current and alternate file to ex.
Regular expressions only work in a |
My RE isn't matching/deleting what I want it to. (Or, "Greedy vs. stingy pattern matching")
The two most common causes for this problem are:
.
metacharacter, and
*
metacharacter. .*
is designed to be "greedy" (i.e., matching as many characters as possible).
Sometimes users need an expression which is "stingy," matching the shortest possible string.
.
metacharacter matches any single character on the line.
(.
cannot match the newline at the end of the line because
the newline is removed when the line is put into the pattern space;
sed
adds a newline when the pattern space is output.).
will match a newline in the middle of the pattern space.
If there are 3 lines in the pattern space, s/.*//
will delete all 3 lines,
not just the first one (leaving 1 blank line, since the trailing newline is added to the output).
Normal misuse of .
occurs in trying to match a word or bounded field, and
forgetting that .
will also cross the field limits.
Suppose you want to delete the first word in braces:
echo {one} {two} {three} | sed 's/{.*}/{}/' # fails
echo {one} {two} {three} | sed 's/{[^}]*}/{}/' # succeeds
s/{.*}/{}/
is not the solution, since the regex .
will match any character,
including the close braces. .
with [^}]
,
which specifies a negated character set [^...]
containing anything other than a right brace. s/{one}/{}/
would also solve our question, but to illustrate the use of the negated character set: [^anything-but-this]
.
A negated character set should be used for matching words between quote marks,
for fields separated by commas, and so on.
*
metacharacter represents zero or more instances of the previous expression.
This looks for the leftmost possible match
echo foo | sed 's/o*/EEE/'will generate
EEEfoo
, not fEEE
because /o*/
matches the null string at the beginning of the word.
After finding the leftmost possible match, the *
is GREEDY; it always tries to match the longest possible string. When two or three instances of .*
occur in the same RE, the leftmost instance will grab the most characters. Consider this example, which uses grouping \(...\)
to save patterns:
echo bar bat bay bet bit | sed s/^.*\(b.*\)/\1/'What will be displayed is
bit
because the leftmost .*
took the longest possible match. Please e-mail me if you find any errors.