Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Operating in a pattern range except for the patterns

You may remember that I mentioned you can do a substitute on a pattern range, like changing "old" to "new" between a begin/end pattern:

#!/bin/sh

sed '

/begin/,/end/ s/old/new/

'

Another way to write this is to use the curly braces for grouping:

#!/bin/sh

sed '

/begin/,/end/ {

s/old/new/

}

'

I think this makes the code clearer to understand, and easier to modify, as you will see below.

If you did not want to make any changes where the word "begin" occurred, you could simple add a new condition to skip over that line:

#!/bin/sh

sed '

/begin/,/end/ {

/begin/n # skip over the line that has "begin" on it

s/old/new/

}

'

However, skipping over the line that has "end" is trickier. If you use the same method you used for "begin" then the sed engine will not see the "end" to stop the range - it skips over that as well. The solution is to do a substitute on all lines that don't have the "end" by using

#!/bin/sh

sed '

/begin/,/end/ {

/begin/n # skip over the line that has "begin" on it

/end/ !{

s/old/new/

}

}

'

Writing a file with the 'w' command

You may remember that the substitute command can write to a file. Here again is the example that will only write lines that start with an even number (and followed by a space):

sed -n 's/^[0-9]*[02468] /&/w even' <file

I used the "&" in the replacement part of the substitution command so that the line would not be changed. A simpler example is to use the "w" command, which has the same syntax as the "w" flag in the substitute command:

sed -n '/^[0-9]*[02468]/ w even' <file

Remember - only one space must follow the command. Anything else will be considered part of the file name. The "w" command also has the same limitation as the "w" flag: only 10 files can be opened in sed.

Reading in a file with the 'r' command

There is also a command for reading files. The command

sed '$r end' <in>out

will append the file "end" at the end of the file (address "$)." The following will insert a file after the line with the word "INCLUDE:"

sed '/INCLUDE/ r file' <in >out

You can use the curly braces to delete the line having the "INCLUDE" command on it:

#!/bin/sh

sed '/INCLUDE/ {

r file

d

}'


Click here to get file: sed_include.sh

The order of the delete command "d" and the read file command "r" is important. Change the order and it will not work. There are two subtle actions that prevent this from working. The first is the "r" command writes the file to the output stream. The file is not inserted into the pattern space, and therefore cannot be modified by any command. Therefore the delete command does not affect the data read from the file.

The other subtlety is the "d" command deletes the current data in the pattern space. Once all of the data is deleted, it does make sense that no other action will be attempted. Therefore a "d" command executed in a curly brace also aborts all further actions. As an example, the substitute command below is never executed:



#!/bin/sh

# this example is WRONG

sed -e '1 {

d

s/.*//

}'


Click here to get file: sed_bad_example.sh

The earlier example is a crude version of the C preprocessor program. The file that is included has a predetermined name. It would be nice if sed allowed a variable (e.g "\1)" instead of a fixed file name. Alas, sed doesn't have this ability. You could work around this limitation by creating sed commands on the fly, or by using shell quotes to pass variables into the sed script. Suppose you wanted to create a command that would include a file like cpp, but the filename is an argument to the script. An example of this script is:

% include 'sys/param.h' <file.c >file.c.new

A shell script to do this would be:

#!/bin/sh

# watch out for a '/' in the parameter

# use alternate search delimiter

sed -e '\_#INCLUDE <'"$1"'>_{

r '"$1"'

d

}'

Let me elaborate. If you had a file that contains

Test first file

#INCLUDE <file1>

Test second file

#INCLUDE <file2>

you could use the command

sed_include1.sh file1<input|sed_include1.sh file2

to include the specified files.


Click here to get file: sed_include1.sh

SunOS and the # Comment Command

As we dig deeper into sed, comments will make the commands easier to follow. The older versions of sed only allow one line as a comment, and it must be the first line. SunOS (and GNU's sed) allows more than one comment, and these comments don't have to be first. The last example could be:

#!/bin/sh

# watch out for a '/' in the parameter

# use alternate search delimiter

sed -e '\_#INCLUDE <'"$1"'>_{

 

# read the file

r '"$1"'

 

# delete any characters in the pattern space

# and read the next line in

d

}'


Click here to get file: sed_include2.sh


Date: 2016-01-14; view: 818


<== previous page | next page ==>
Ranges by line number | Adding, Changing, Inserting new lines
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.007 sec.)