You could pipe the file through sed and then redi-rect the sed output to another file; once the output has been validated, you could move the modified file back into place and either ove
Trang 1■ ■ ■
Editing Files in Place
Sometimes you want to modify a file as part of the tasks run from a shell script Although
the use of sed to modify files on the fly is common, the use of ed is less familiar to many ed
is a line-oriented editor that works much like any other text editor It opens a file, makes
modifications, saves the changes, and exits The advantage of using ed to script these
interactive sessions is that the modification is performed directly on the file itself and the
results are neither redirected to another file nor used to overwrite the file itself
For example, you might want to process a large list of files, applying a single
modifica-tion to all of the files In most of these cases, the modificamodifica-tion may not be more than a
simple search-and-replace operation You could pipe the file through sed and then
redi-rect the sed output to another file; once the output has been validated, you could move
the modified file back into place and either overwrite the original or, more conservatively,
back up the original file to another location before replacing it with the modified version
The alternate method discussed here carries a little more risk because the original file
itself is modified There is a chance that the system will crash during the editing process
for reasons not related to editing Disk failures do occur on occasion, and it is also possible
that another user might be modifying the file at the same time that you make changes of
your own, or simply that your modification is incorrect and isn’t validated The upside is
that editing files with ed works well and there isn’t any need to create temporary files while
modifications are in progress, although you may want to back up the original files for
safety
The procedure in this chapter uses the ed utility to modify files in place ed is not a
full-screen interactive editor, and any modification you want to perform on a file needs to be
specified by an ed command These commands include moving to specific locations in a
file, searching and replacing, inserting and deleting data, and so on When you script the
use of ed, you first create a file containing all the modification commands you want to
apply to the target file Once that command file is created, you then apply all the
com-mands at once to the target file
This discussion will focus mainly on performing search-and-replace commands, plus
a couple of other types of edits The ed editor can do much more than what I’m going to
suggest here, but this chapter will give you a good start on this style of editing
Trang 2Simple Search and Replace with ed
The following code is the simplest example It shows the contents of a file named ed.script that contains an ed script consisting of a single search-and-replace command:
g/search/s/search/replace/g
w
q
The script saves the newly modified file and quits A more advanced script would con-tain many more commands, but the final two write (w) and quit (q) lines would remain the same The script can then be applied to a target file
The ed command file is redirected into ed, which is then run against the target file The -s switch suppresses diagnostic information
ed -s /target/file < ed.script
The following is a slightly different method of creating ed input without the need for a separate script file:
ed -s /target/file <<EOF
g/search/s/search/replace/g
w
q
EOF
Note that the script’s text is redirected into the ed command in the form of a here-doc-ument for input; in this case the delimiter is EOF You then give the commands you desire, and complete the here-document with an ending delimiter This is very similar to the dis-cussion of free-formatted output using cat found in Chapter 28
Now that the mechanics of how to create the command file and use it are set, let me explain some of the commands in more detail
Search and Replace Using ed, Dissected
Now I want to explain, using the search-and-replace command from the preceding ed.script, what parts make up the search-and-replace instruction and what they do This command is composed of six elements delimited by forward slashes (/)
g/search/s/search/replace/g
The first element, g for “global,” instructs ed to perform the search-and-replace task throughout the entire target file This element is optional Without it, ed would default to
editing only the first line that matches the search.
The second element describes what you are searching for in the target file
Trang 3The third element, the s, is fairly simple as well: it tells ed to search for the fourth
ele-ment At first this doesn’t make sense, as the second element already provided the search
string Read on to see why it’s necessary
The fourth element is a secondary search term It qualifies the search specified by the
first search term (the second element of the command) For example, say you had a file
containing names and addresses in which the first field of each line was either Name or
Address, indicating what information follows If you wanted to modify a particular street
name and did a simple search and replace, you might end up inadvertently modifying
some personal names as well as the desired street names With the technique shown here,
you could search for all lines starting with Address, and then (using the secondary search
term) search for and modify a specific street name within these lines This gives you more
control over how the term that is to be modified is matched
The fifth element specifies what will replace the fourth element
The final element is another g, once more representing a global replacement Again,
this element is optional This g tells ed to make the replacement for all instances of the
secondary search term on lines that match the primary search string If the second g
is not present, the replacement will be performed on only the first match of the
second-ary search string Any subsequent matches of the secondsecond-ary string on that line will be
ignored
Examples of ed Commands
The following code represents the target file for each of the examples of ed
search-and-replace commands provided in this section As you can see, it is part of a hosts file I have
left the final w and q entries out of the displayed ed scripts In practice you wouldn’t want
to forget these, as the changes then wouldn’t be saved when ed completes After the entry
or entries that would be in the ed script file, I explain what the code will do, and finally I
show you the modifications
172.16.5.1 node1 node1.somedomain.com alias1.somedomain.com
172.16.5.2 node2 node2.somedomain.com alias2.somedomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
The following command searches for occurrences of somedomain in the lines of the
file and, on each line where this string is found, replaces all entries of somedomain with
newdomain
ed Command
g/somedomain/s/somedomain/newdomain/g
Trang 4Modified File
172.16.5.1 node1 node1.newdomain.com alias1.newdomain.com
172.16.5.2 node2 node2.newdomain.com alias2.newdomain.com
172.16.5.4 node3 node3.newdomain.com alias3.newdomain.com
The next example replaces all occurrences of somedomain with newdomain on the first line where the somedomain string is found:
ed Command
/somedomain/s/somedomain/newdomain/g
Modified File
172.16.5.1 node1 node1.newdomain.com alias1.newdomain.com
172.16.5.2 node2 node2.somedomain.com alias2.somedomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
The following command replaces the first instance of somedomain with newdomain on the first line where the somedomain string is found:
ed Command
/somedomain/s/somedomain/newdomain/
Modified File
172.16.5.1 node1 node1.newdomain.com alias1.somedomain.com
172.16.5.2 node2 node2.somedomain.com alias2.somedomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
Here we replace all instances of the somedomain string with newdomain on all the lines where the IP address 172.16.5.2 is found:
ed Command
g/172.16.5.2/s/somedomain/newdomain/g
Modified File
172.16.5.1 node1 node1.somedomain.com alias1.somedomain.com
172.16.5.2 node2 node2.newdomain.com alias2.newdomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
Trang 5The next command lets us replace all instances of somedomain with newdomain in the file
whenever an entry for the 172.16.5 subnet is found:1
ed Command
g/^172.16.5/s/somedomain/newdomain/g
Modified File
172.16.5.1 node1 node1.newdomain.com alias1.newdomain.com
172.16.5.2 node2 node2.newdomain.com alias2.newdomain.com
172.16.5.4 node3 node3.newdomain.com alias3.newdomain.com
In the next example, we search for node2 and insert a new entry prior to the line that is
found There are three commands:
1. The search for the term where you want to insert the new text
2. The i for inserting the new text This command switches the editor into insert
mode instead of command mode, similar to the vi editor Now comes the text
of the line you want to insert
3. The final command is the single period (.) This returns the editor to command
mode
ed Commands
/node2
i
172.16.5.14 node14 node14.newdomain.com alias14.newdomain.com
Modified File
172.16.5.1 node1 node1.somedomain.com alias1.somedomain.com
172.16.5.14 node14 node14.newdomain.com alias14.newdomain.com
172.16.5.2 node2 node2.somedomain.com alias2.somedomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
In the next example, we search for node2 and insert another entry following the line that
is found This command sequence is nearly identical to the previous example, with only a
slight modification so the new text follows the line that was found in the search The i
command to insert the new text has been replaced with the a to append the new text The
text and the closing period remain unchanged
1 Note the leading carat (^) in the subnet that specifies lines beginning with that subnet Without this
character, IP addresses that simply contain 172.16.5 also would be replaced.
Trang 6ed Commands
/node2
a
172.16.5.14 node14 node14.newdomain.com alias14.newdomain.com
Modified File
172.16.5.1 node1 node1.somedomain.com alias1.somedomain.com
172.16.5.2 node2 node2.somedomain.com alias2.somedomain.com
172.16.5.14 node14 node14.newdomain.com alias14.newdomain.com
172.16.5.4 node3 node3.somedomain.com alias3.somedomain.com
This last example shows how to delete a line entirely We search for a line containing the string node2 and delete it This command deletes only the first line that is found in the file A leading g on the command would implement the deletion for all lines found in the file
ed Command
/node2/d
Modified File
172.16.5.1 node1 node1.newdomain.com alias1.newdomain.com
172.16.5.4 node3 node3.newdomain.com alias3.newdomain.com
You should now be able to start using ed effectively Take note again that the ed input can contain multiple entries to perform several tasks on a single file Often the desired search strings or their replacements become known just before the target file is manipu-lated For example, your ed command input may depend on accessing variables that were set prior to creating the ed script For more examples of this technique in action, take a look at the scripts in Chapters 36 and 37
Escaping Special Characters in a File
The following is a short script to escape all the special characters in a file that is specified from the command line The script is meant to be a baseline that can escape any char-acter, though you will likely tailor it to your own needs The script performs its task using here-document syntax The here-document notation can be found in the shell manual page
The script starts simply enough The usage is defined and then the input is validated to make sure a file is specified and that it exists
Trang 7usage="$0 {target file containing any special characters to be escaped}"
if [ $# -eq 0 ]
then
echo $usage
exit 1
fi
if [ ! -f $1 ]
then
echo File $1 does not exist
echo $usage
exit 1
else
file=$1
fi
If these requirements aren’t met, the script displays the usage information and exits
The following code starts the here-document for input to the ed command:
ed -s $file <<EOF
g/[\]/s/[\]/\\\\\\\/g
The first search and replace is for the escape character itself This replacement must be
first or it will replace the backslash of characters that have already been escaped
These replacements are the most simple of the bunch:
g/ /s/ /\\\ /g
g/!/s/!/\\\!/g
g/@/s/@/\\\@/g
g/#/s/#/\\\#/g
g/,/s/,/\\\,/g
g/%/s/%/\\\%/g
This grouping of replacements could have been written with the search character
being surrounded by square brackets instead of the double escape There isn’t any
differ-ence in the length of the lines and it can be written either way
g/\\$/s/\\$/\\\\$/g
g/\\&/s/\\&/\\\\&/g
g/\\*/s/\\*/\\\\*/g
The following set of replacement characters doesn’t work with the search character
sur-rounded by square brackets They must be escaped so they aren’t interpreted by the shell
g/\\;/s/\\;/\\\;/g
g/\\:/s/\\:/\\\:/g
g/\\[/s/\\[/\\\[/g
g/\\]/s/\\]/\\\]/g
g/\\^/s/\\^/\\\\^/g
g/\\\`/s/\\\`/\\\\\`/g
Trang 8This large section of replacements demonstrates the search character being specified
by containing it within the square brackets The replacement is still an escaped value g/[/]/s/[/]/\\\\//g
g/[(]/s/[(]/\\\(/g
g/[)]/s/[)]/\\\)/g
g/[+]/s/[+]/\\\+/g
g/[=]/s/[=]/\\\=/g
g/[{]/s/[{]/\\\{/g
g/[}]/s/[}]/\\\}/g
g/[|]/s/[|]/\\\|/g
g/[']/s/[']/\\\'/g
g/["]/s/["]/\\\"/g
g/[<]/s/[<]/\\\</g
g/[>]/s/[>]/\\\>/g
g/[?]/s/[?]/\\\?/g
g/[~]/s/[~]/\\\~/g
g/[-]/s/[-]/\\\-/g
g/[_]/s/[_]/\\\_/g
The script finally completes by closing the here-document This finishes the input to the ed command, and the modifications are then made to the input file
w
q
EOF