tags:

views:

673

answers:

5

How can I extract certain variables from a specific range of lines in sed/awk?

Example: I want to exctract the host and port from .tnsnames.ora from this section that starts at line 105.

DB_CONNECTION=
   (description=
     (address=
         (protocol=tcp)
         (host=127.0.0.1)
         (port=1234)
      )
      (connect_data=
         (sid=ABCD)
         (sdu=4321)
  )
+1  A: 

use:

sed '105,$< whatever sed code you want here >'

If you specifically want the host and the port you can do something like:

sed .tnsnames.ora  '105,115p'|grep -e 'host=' -e 'port='
Nathan Fellman
A: 

This seems to do the trick, but is this the best way?

BEGIN {
    FS="="
}

{
    if(NR>105 && NR<115)
    {
        gsub(/\)/,"",$0)
        if(/host/) {
            HOST=$2
        }
        else if (/port/) {
            PORT=$2
        }
    }
}
lk
+1  A: 

You can use address ranges to specify to which section to apply the regular expressions. If you leave the end line address out (keep the comma) it will match to the end of file. You can also 'chain' multiple expressions by using '-e' multiple times. The following expression will just print the port and host value to standard out. It uses back references (\1) in order to just print the matching parts.

sed -n -e '105,115s/(port=\([0-9].*\))/\1/p' -e '105,115s/(host=\([0-9\.].*\))/\1/p' tnsnames.ora
Hardy
+1  A: 

The gawk can use regular expression in field separater(FS).

'$0=$2' is always true, so automatically this script print $2.

$ gawk -F'[()]' 'NR>105&&NR<115&&(/host/||/port/)&&$0=$2' .tnsnames.ora
Hirofumi Saito
A: 

@lk, to address the answer you posted:

You can write awk code like C, but it's more succinctly expressed as "pattern {action}" pairs.

If you have gawk or nawk, the field separator is an ERE as Hirofumi Saito said

gawk -F'[()=]' '
    NR < 105 {next}
    NR > 115 {exit}
    $2 == "host" || $2 == "port" {
        # do stuff with $2 and $3
        print $2 "=" $3
    } 
'
glenn jackman