Wednesday, June 20, 2012

Insert a line before or after a pattern



  In this article, we will see the different ways in which we can insert a line before or after on finding a pattern.  On finding the pattern 'Fedora', the requirement is to insert a line:
  • before the pattern 
  • after the pattern.
Let us consider a file with the following contents:
$ cat file
Linux
Solaris
Fedora
Ubuntu
AIX
HPUX
Inserting before the pattern:

1. awk solution.
$ awk '/Fedora/{print "Cygwin"}1' file
Linux
Solaris
Cygwin
Fedora
Ubuntu
AIX
HPUX
The '1' at the end prints every line by default. On finding the pattern 'Fedora', 'Cygwin' is printed. Hence, first  "Cygwin" gets printed followed by 'Fedora'(1).

2. sed solution which is simple.
$ sed 's/.*Fedora.*/Cygwin\n&/' file
Linux
Solaris
Cygwin
Fedora
Ubuntu
AIX
HPUX
  On finding the pattern 'Fedora', substitute with 'Cygwin' followed by the pattern matched.

3. Perl solution:
$ perl -plne 'print "Cygwin" if(/Fedora/);' file
Linux
Solaris
Cygwin
Fedora
Ubuntu
AIX
HPUX
 The 'p' option is the alternative for the '1' in awk, prints every line by default. Rest is self-explanatory.

4. Pure bash shell script solution:
#!/usr/bin/bash

while read line
do
        echo $line | grep -q "Fedora"
        [ $? -eq 0 ] && echo "Cygwin"
        echo $line
done < file
   A line is read. grep -q is silent grep where the result, if any, will not be displayed.  The status($?) will be 0 if a match is found and hence 'Cygwin' is printed.

Inserting after the Pattern:

5. awk solution
$ awk '/Fedora/{print;print "Cygwin";next}1' file
Linux
Solaris
Fedora
Cygwin
Ubuntu
AIX
HPUX
  The difference here is the addition of two extra commands: print and next. print will print the current line, and the next command will skip the current line from printing again.

6. sed solution:
$ sed 's/.*Fedora.*/&\nCygwin/' file
Linux
Solaris
Fedora
Cygwin
Ubuntu
AIX
HPUX
  Simple change from the earlier sed solution. Patten matched(&) followed by "Cygwin".

7. perl solution.
$ perl -lne 'print $_;print "Cygwin" if(/Fedora/);' file
Linux
Solaris
Fedora
Cygwin
Ubuntu
AIX
HPUX
    The default printing command 'p' is removed and simply every line is printed using special variable $_.

8. Bash shell script for inserting after the pattern:
#!/usr/bin/bash

while read line
do
        echo $line
        echo $line | grep -q "Fedora"
        [ $? -eq 0 ] && echo "Cygwin"
done < file

13 comments:

  1. Super clear and comprehensive, exactly what I've been looking for.

    ReplyDelete
  2. Thanks a toon, saved me a lot of time editing a 20k+ file and adding some 1500+ lines.

    ReplyDelete
  3. And how to write the Output back into file?

    only get an empty file oder without any wordwrap

    ReplyDelete
  4. Hi, i work fine for me but when i read the file again no change has happened. How do you do it to rewrite to file. Thanks

    ReplyDelete
  5. to affect the change in file, use sed with -i option.

    ReplyDelete
    Replies
    1. Any chance on expanding with an example please? Thanks

      Delete

  6. Input file
    -----------
    10:44 /usr/IBM/WebSphere/7.0/AppServer/java/bin/java jasper-compiler.jar
    /usr/IBM/WebSphere/8.0/AppServer/java/bin/java -Declipse.security
    /usr/IBM/WebSphere/6.0/AppServer/java/bin/java -Declipse.security
    0 Jul 24 - 5:38 /usr/IBM/WebSphere/5.5/AppServer/java/bin/java
    Jul 24 - 5:38 /usr/IBM/WebSphere/7.5/AppServer/java/bin/java

    Looking for below output
    -------------------------
    /usr/IBM/WebSphere/7.0/AppServer/java/bin/java
    /usr/IBM/WebSphere/8.0/AppServer/java/bin/java
    /usr/IBM/WebSphere/6.0/AppServer/java/bin/java
    /usr/IBM/WebSphere/5.5/AppServer/java/bin/java
    /usr/IBM/WebSphere/7.5/AppServer/java/bin/java


    Can someone please help me on getting above output

    ReplyDelete
  7. I like this article, it would be good if there were examples that made changes to the file. I know sed has -i and perl can do it, but awk can't from what I understand.

    ReplyDelete
  8. How can we delete before the pattern

    ReplyDelete