Friday 25 January 2013

Unix Sed Command & hand-on


SED (Stream Editor)

 
Syntex:-

                        Sed options ‘address action’ file(s)

Sed uses instruction to act on text. An instruction combines an address for selecting lines,with an action to be taken on them.

Command  : s for Substitution

Sed has several commands, but most people only learn the substitute command: s. The substitute command changes all occurrences of the regular expression into a new value. A simple example is changing "day" in the "old" file to "night" in the "new" file:

                                   sed s/day/night/ old >new

 

If you have meta-characters in the command, quotes are necessary. And if you aren't sure, it's a good habit, and I will henceforth quote future examples to emphasize the "best practice." Using the strong (single quote) character, that would be:

sed 's/day/night/'  old >new

There are four parts to this substitute command:

s         Substitute command
/../../   Delimiter
day       Regular Expression Pattern Search Pattern
night     Replacement string

Slash as a delimiter:-

If you want to change a pathname that contains a slash - say /usr/local/bin to /common/bin you could use “|” to quote the slash:-

sed 's|/usr/local/bin|/common/bin|' <old >new

Using & as a matched String:-

Sometimes you want to search for a pattern and add some characters, like parenthesis, around or near the pattern you found. It is easy to do this if you are looking for a particular string:

sed 's/abc/(abc)/' <old >new               This will not work

The solution requires the special character "&." It corresponds to the pattern found.

sed 's/[a-z]*/(&)/' <old >new

 

Substitution flag:-

/g - Global Replacement:-

Most Unix utilties work on files, reading a line at a time. Sed, by default, is the same way. If you tell it to change a word, it will only change the first occurrence of the word on a line. You may want to make the change on every word on the line instead of the first.If you want it to make changes for every word, add a "g" after the last delimiter and use the work-around:

sed 's/[^ ][^ ]*/(&)/g' <old >new

 
/1,/2,etc. Specifying Which occurance:-

 

If you want to modify a particular pattern that is not the first one on the line,if you want to delete the second word on the line then use this command:-

 

sed 's/[a-zA-Z]* //2' <old >new

 

You can add a number after the substitution command to indicate you only want to match that particular pattern.

 

You can combine a number with the g (global) flag. For instance, if you want to leave the first world alone , but change the second, third, etc. to DELETED, use /2g:

 

sed 's/[a-zA-Z]* /DELETED /2g' <old >new

 
Write To a File with /w filename:-

There is one more flag that can follow the third delimiter. With it, you can specify a file that will receive the modified data. An example is the following, which will write all lines that start with an even number to the file even:

 

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

 

You must have exactly one space between the w and the filename.
Ex:-

1)      sed –n ‘1,500w foo1           ---Saves 1 to 500 to foo1

501,$w foo2’ foo.main        ----- from 501 to last line to foo2

 

Multiple Command with –e command:-

One method of combining multiple commands is to use a -e before each command:

sed -e 's/a/A/' -e 's/b/B/' <old >new
 

Filenames On the Command Line:-

You can specify files on the command line if you wish.

 

sed -e 's/^#.*//' f1 f2 f3 | grep -v '^$' | wc –l

 

The sed substitute command changes every line that starts with a "#" into a blank line.

Grep was used to filter out empty lines.

Wc counts the number of lines left.

 

Note :-^ sign shows start line.

            $ shows end of the line.

Sed –n Option:-No Printing 

The "-n" option will not print anything unless an explicit request to print is found.
Eg:-

          sed –n ‘1,2p’ <filename>

This command will print the first two lines of file( head -2 <filename>)

          sed –n ‘$p’  <filename >

Print the last line .( tail -1 <filename>)
        

Negating the Action:-

     Sed –n ‘3,$!p’ <filename>        Don’t print from line 3 to end
 

Deleting Line:-  sed use –d (delete) command to emulate grep –v option of selection lines not containing the pattern .

e.g.

Sed ‘/director/d’ emp.lst >olist

Sed –n ‘/director/!p’ emp.lst > olist     ( -n option is not used with d )

 -> select all lines except those containing  director and save in olist.

Pattern:-

Sed uses the same convention, provided you terminate the expression with a slash.

To delete the first number on all lines that start with a "#," use:

sed '/^#/  s/[0-9][0-9]*//'

 

Suppose you wanted to search for the string "/usr/local/bin" and you wanted to change it for "/common/all/bin." You could use the backslash to escape the slash:

 
   sed '/\/usr\/local\/bin/ s/\/usr\/local/\/common\/all/'

   sed 's/foo/bar/g' filename         # standard replace command

   sed '/foo/ s/foo/bar/g' filename   # executes more quickly
 

Range By Line Number:-

 You can specify a range on line numbers by inserting a comma between the numbers. To restrict a substitution to the first 100 lines, you can use:

sed '1,100 s/A/a/'

Range By Pattern:-

sed '/start/,/stop/ s/#.*//'

This example will remove comments everywhere except the lines between the two keywords:

sed -e '1,/start/ s/#.*//' -e '/stop/,$ s/#.*//'

eg:-
sed -e 's/#.*//' -e '/^$/ d'   (Removing comments and blank lines takes two commands. The first removes every character from the "#" to the end of the line, and the second deletes all blank lines: )

 
Relationship with d  ,  p & !

 
  Sed      Range   Command   Results
  --------------------------------------------------------
  sed -n   1,10    p         Print first 10 lines (head -10)
  sed -n   11,$    !p        Print first 10 lines
  sed      1,10    !d        Print first 10 lines
  sed      11,$    d         Print first 10 lines
  --------------------------------------------------------
  sed -n   1,10    !p        Print last 10 lines (tail -10 )
  sed -n   11,$    p         Print last 10 lines
  sed      1,10    d         Print last 10 lines
  sed      11,$    !d        Print last 10 lines
  --------------------------------------------------------
  sed -n   1,10    d         Nothing printed
  sed -n   1,10    !d        Nothing printed
  sed -n   11,$    d         Nothing printed
  sed -n   11,$    !d        Nothing printed
  --------------------------------------------------------
  sed      1,10    p         Print first 10 lines twice,
                            Then next 10 lines once
  sed      11,$    !p        Print first 10 lines twice,
                            Then last 10 lines once
  --------------------------------------------------------
  sed      1,10    !p        Print first 10 lines once,
                            Then last 10 lines twice
  sed      11,$    p         Print first 10 lines once,
                            then last 10 lines twice

Hand-on sed:-


 # double space a file

 sed G


 # triple space a file

 sed 'G;G'


 # count lines (emulates "wc -l")

 sed -n '$='

 

# Remove ^M character

#in bash/tcsh, press Ctrl-V then Ctrl-M

sed '1,$  s/^M//g'  filename   

 

# delete leading whitespace (spaces, tabs) from front of each line

 # aligns all text flush left

 sed 's/^[ \t]*//'                    # see note on '\t' at end of file

 
# delete trailing whitespace (spaces, tabs) from end of each line

 sed 's/[ \t]*$//'                    # see note on '\t' at end of file

 

# delete BOTH leading and trailing whitespace from each line

 sed 's/^[ \t]*//;s/[ \t]*$//'

 
# substitute (find and replace) "foo" with "bar" on each line

 sed 's/foo/bar/'             # replaces only 1st instance in a line

 sed 's/foo/bar/4'            # replaces only 4th instance in a line

 sed 's/foo/bar/g'            # replaces ALL instances in a line

 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # replace the next-to-last case

 sed 's/\(.*\)foo/\1bar/'            # replace only the last case

 
# substitute "foo" with "bar" ONLY for lines which contain "baz"

 sed '/baz/s/foo/bar/g'

 

# substitute "foo" with "bar" EXCEPT for lines which contain "baz"

 sed '/baz/!s/foo/bar/g'

 

 

 # print the line immediately before a regexp, but not the line

 # containing the regexp

 sed -n '/regexp/{g;1!p;};h'

 

 

 # print the line immediately after a regexp, but not the line

 # containing the regexp

 sed -n '/regexp/{n;p;}'

 # print only lines of 65 characters or longer

 sed -n '/^.\{65\}/p'

 

# print only lines of less than 65 characters

 sed -n '/^.\{65\}/!p'


 # print line number 52

 sed -n '52p'                 # method 1

 sed '52!d'                   # method 2

 sed '52q;d'                  # method 3, efficient on large files


 

No comments:

Post a Comment