more on vi and grep and REGULAR EXPRESSIONS here is continued what i was showing you today about vi at your house. i fixed the fuck up i had at your house. i tested all the stuff so unless i really fucked up all the command im showing here should workhere is a file list
_VIMRC 108 02-01-01 1:01p NUMIT 5 03-03-01 6:19p KRAPOLA 1,223 03-31-01 9:42p CWSDPMI EXE 20,473 10-19-97 9:48p GREP EXE 89,679 03-28-95 5:14p MIME EXE 23,436 02-01-95 4:22p PERL4 EXE 353,568 03-01-92 12:54p PKZIP EXE 42,166 02-01-93 2:04a SED EXE 22,104 10-01-91 11:58a VI EXE 597,504 08-30-98 4:19p ZIP2EXE EXE 27,319 02-01-93 2:04a
and i want to change every file that has an extension from
xxxxxxxx xxx to xxxxxxxx.xxx
the G and S commands are used to do this. the G command works like this
:%g/expression/command
for every line the expression is found on the command is executed.
in this case i go
:%g/^..........[^ ]/command
that command says find every line where the 10th character of the line is not a space and execute the command. the regular expression means
:%g/^..........[^ ]/command -xxxxxxxxxx---- | | | | | +--match a single character thats not a space | | | +--------- . matches any character. | so this part matches any 9 characters | +-------------- ^ says match at the begining of the line
the command will be
s/ */./
which says change one space followed by zero or more spaces to a ".". note in the command their is two spaces in the first part. this forces at least one space to be found.
the full command will be
:%g/^..........[^ ]/s/ */./
the results are.
_VIMRC 108 02-01-01 1:01p NUMIT 5 03-03-01 6:19p KRAPOLA 1,223 03-31-01 9:42p CWSDPMI.EXE 20,473 10-19-97 9:48p GREP.EXE 89,679 03-28-95 5:14p MIME.EXE 23,436 02-01-95 4:22p PERL4.EXE 353,568 03-01-92 12:54p PKZIP.EXE 42,166 02-01-93 2:04a SED.EXE 22,104 10-01-91 11:58a VI.EXE 597,504 08-30-98 4:19p ZIP2EXE.EXE 27,319 02-01-93 2:04a
the g command is where GREP got its name.
grep prints all the lines that match a regular expression. to do that in vi or ex you would use the G command followed by a /Regular Expression/ followed by the P command to print the line if it matches the regular expression giving
g/Regular Expression/p
which leads to
GREP
the g command can also be used to run a command on all lines that dont match the regular expression. using a ! befor the regular expression
:%g!/expression/command
i use this command to delete all the lines in a file which dont contain internet email addresses link snail@aztec.asu.edu
which says if the line doesnt have a '@' in it run the d command which deletes the line.
this is where i fucked up the demo at your house trying to show you how to swap two fields. its done like this here are the lines
_VIMRC 108 02-01-01 1:01p NUMIT 5 03-03-01 6:19p KRAPOLA 1,223 03-31-01 9:42p CWSDPMI.EXE 20,473 10-19-97 9:48p GREP.EXE 89,679 03-28-95 5:14p MIME.EXE 23,436 02-01-95 4:22p PERL4.EXE 353,568 03-01-92 12:54p PKZIP.EXE 42,166 02-01-93 2:04a SED.EXE 22,104 10-01-91 11:58a VI.EXE 597,504 08-30-98 4:19p ZIP2EXE.EXE 27,319 02-01-93 2:04a
and i will swap the file name with the file size with this command
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 /
108 _VIMRC 02-01-01 1:01p 5 NUMIT 03-03-01 6:19p 1,223 KRAPOLA 03-31-01 9:42p 20,473 CWSDPMI.EXE 10-19-97 9:48p 89,679 GREP.EXE 03-28-95 5:14p 23,436 MIME.EXE 02-01-95 4:22p 353,568 PERL4.EXE 03-01-92 12:54p 42,166 PKZIP.EXE 02-01-93 2:04a 22,104 SED.EXE 10-01-91 11:58a 597,504 VI.EXE 08-30-98 4:19p 27,319 ZIP2EXE.EXE 02-01-93 2:04a
the reason i fucked it up at you house was because i didnt allow for the fact that there were mutiple spaces between the filename and file size.
here is the command disected and analyized four times to show you what it did
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 / ---------------------- ------ | | | +---- this is what 1st expression | is changed to | +--------------------- this is expression thats changed
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 / -- -- -- -- xxxxxxxxx xxxxxxxxx - 2nd pair of \( \) | will become \2 on | change side - ie: file size | +------------------ 1st pair of \( \) will become \1 on change side - ie: file name
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 / ----- --- ----- | | | | | +---- find 0 or more characters that | | are not spaces. ie the file size | | | +---------- this is 2 spaces followed by a * | it says find at least one space | followed by zero or more spaces. | this ends up being the space that | seperate the file name and file size | +----------------- this says find 0 or more characters that are not spaces. ie: the file name
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 / -- -- | | | +-- \1 was defined by the first \( \) | and contains the file name | +----- \2 was defined by the 2nd \( \) and contains the file size
whew! lots of vi. well really lots of Regular Expressions.
on thing that different was at your house the files had leading spaces in front of them. in the prior example i cheated and didnt have leading spaces.
the command has to be modified to work with leading spaces in this example
_VIMRC 108 02-01-01 1:01p NUMIT 5 03-03-01 6:19p KRAPOLA 1,223 03-31-01 9:42p CWSDPMI.EXE 20,473 10-19-97 9:48p GREP.EXE 89,679 03-28-95 5:14p MIME.EXE 23,436 02-01-95 4:22p PERL4.EXE 353,568 03-01-92 12:54p PKZIP.EXE 42,166 02-01-93 2:04a SED.EXE 22,104 10-01-91 11:58a VI.EXE 597,504 08-30-98 4:19p ZIP2EXE.EXE 27,319 02-01-93 2:04a
i changed the command from this
:%s/\([^ ]*\) *\([^ ]*\) /\2 \1 /
to this go get it to work
:%s/\([^ ][^ ]*\) *\([^ ]*\) /\2 \1 /
the only difference is i added a 2nd
[^ ] to
:%s/\([^ ][^ ]*\) *\([^ ]*\) /\2 \1 / ---- to the part that finds the file name this forces the file name to be at least one nonblank character followed by zero or more nonblank characters. in the case where we have leading blanks this is required. in the prior example we didnt need it because the filename was always the 1st character on the line and matched.
if we dont use it here we get burnt because [^ ]* matches ZERO non blank characters and becomes \1 which is NULL and isnt what we want for the filename
followed by a bunch of spaces
followed by several nonblank characters which will be the filename for \2 instead of \1
108 _VIMRC 02-01-01 1:01p 5 NUMIT 03-03-01 6:19p 1,223 KRAPOLA 03-31-01 9:42p 20,473 CWSDPMI.EXE 10-19-97 9:48p 89,679 GREP.EXE 03-28-95 5:14p 23,436 MIME.EXE 02-01-95 4:22p 353,568 PERL4.EXE 03-01-92 12:54p 42,166 PKZIP.EXE 02-01-93 2:04a 22,104 SED.EXE 10-01-91 11:58a 597,504 VI.EXE 08-30-98 4:19p 27,319 ZIP2EXE.EXE 02-01-93 2:04a
final useless commands. all the ex commands which begin with a : work like this
:s/xxx/yyy/ - operates on current line only - no line range was given :%s/xxx/yyy/ - % says operate on all lines :22g/RE/p - 22 says operate on line 22 :22,300g/RE/p - 22,300 says operate on lines 22 thru 300 :.g/RE/p - . says operate on current line :$g/RE/p - $ says operate on LAST line :.,$g/RE/p - .,$ says operate on current thru last line :.+3,$-1g/RE/p - you can do math .+3 says start with 3 lines past current line $-1 says end 1 line before last line
in a s command (change) command if you use a & in the 2nd part of the change it matches what was found in the 1st part.
s/dog/big &/ - changes dog go big dog same as s/dog/big dog/
but this is a better example. take these 2 lines
www.geocities.com/crazy_atheist www.geocities.com/hashish_arizona
this command
:%s/.*/<a href="http:\/\/&">&<\/a>/
changes the prior two lines to
<a href="http://www.geocities.com/crazy_atheist">www.geocities.com/crazy_atheist</a> <a href="http://www.geocities.com/hashish_arizona">www.geocities.com/hashish_arizona</a>
and i do stuff like this all the time