Indi59
Indi59

Reputation: 181

awk, extract specifics values from a file

From a file, i want to extract specific values with awk:

input file:

 EVS 58 (EVSTEST1):
             Export name: /EXPORT1
             Export path: /opt/export1
       File system label: fs_test1
        File system size: 18.7 GB  File system free space: 16.5 GB
       File system state: 
                formatted = Yes
                  mounted = Yes
                   failed = No
         thin provisioned = No
        Access snapshots: No
       Display snapshots: No
           Read Caching: Disabled Disaster recovery setting:
         Recovered = No  Transfer setting = Use file system default

    Export configuration:


 EVS 59 (EVSNEXT):

             Export name: /next
             Export path: /next
       File system label: fs_next
        File system size: 9.75 GB  File system free space: 2.28 GB
       File system state: 
                formatted = Yes
                  mounted = Yes
                   failed = No
         thin provisioned = No
        Access snapshots: No
       Display snapshots: No
            Read Caching: Disabled Disaster recovery setting:
         Recovered = No  Transfer setting = Use file system default

    Export configuration:
 10.26.xx.xx(rw,norootsquash)
 10.26.xx.xx(rw,norootsquash)
 10.26.xx.xx(rw,norootsquash)

I need to extract lines: EVS & EVS ID, Export name, Export path, File system label and Export configuration if present.

to get the following output:

  58;EVSTEST1;/EXPORT1;/opt/export1;fs_test1;-
  59;EVSNEXT;/next;/next;fs_next;10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash)

But, with my script bellow, i can't get all "Export configuration" lines. i got only the fisrt. I tried with for loop, several if without success..

#!/bin/bash

LST_NFS=$(cat lst_nfs.txt | awk -F= '\
    ($1~/^EVS/) { gsub(/\(/,"" );gsub(/\)/,"" ) ; gsub(/:/,"" ); split($0,parts," ") ;evsid=parts[2];evsname=parts[3] }
    ($1~/            Export name/) { split($0,parts," ") ; name=parts[3] }
    ($1~/            Export path/) { split($0,parts," ") ; path=parts[3] }
    ($1~/      File system label/) { split($0,parts," ") ; fs=parts[4] }
    ($1~/   Export configuration:/) { getline;
        if ( $1~ /^[0-9]+/) { export1=$1; getline;
        printf "%s;%s;%s;%s;%s;%s\n",evsid,evsname,name,path,fs,export1}
        else { export1="-";
                printf "%s;%s;%s;%s;%s;%s\n",evsid,evsname,name,path,fs,export1 }

    }')
    echo -e "$LST_NFS"

My script result:

57;EVSTEST1;/EXPORT1;/opt/export1;fs_test1;-
59;EVSNEXT;/next;/next;fs_next;10.26.xx.xx(rw,norootsquash)

Many thanks for your help.

regards,

Greg

Upvotes: 3

Views: 119

Answers (2)

karakfa
karakfa

Reputation: 67467

awk to the rescue!

can be written better, but works for your file if your format is standard.

$ awk -v RS="\n\n\n" -v OFS=';' '
    {for(i=1;i<=NF;i++) 
         if($i" "$(i+1)=="Export configuration:") {c=i; break}
     if(c) for(j=c+2;j<=NF;j++) 
               {e=e sep $j; sep=OFS} 
     else e="-"; 
     sub(/\(/,"",$3);sub(/\):/,"",$3);
     print $1$2,$3,$6,$13,e; c=0}' file

EVS58;EVSTEST1;/EXPORT1;fs_test1;
EVS59;EVSNEXT;/next;fs_next;10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash)

Note that this requires multi-char record separator in gawk, your awk may or may not support.

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203189

Whenever you ave name = value pairs in your input data it's a good idea to create a name2value array and then just print whatever you like by it's name:

$ cat tst.awk
BEGIN { OFS=";" }

{ gsub(/^[[:space:]]+|[[:space:]]+$/,"") }

$1=="EVS" {
    gsub(/[()]/,"")
    n2v["EVS"] = $2
    n2v["EVS ID"] = $3
}

inEC {
    if (NF) {
        n2v[name] = (name in n2v ? n2v[name] OFS : "") $0
    }
    else {
        n2v[name] = (name in n2v ? n2v[name] : "-")
        prtRec()
        delete n2v
        inEC = 0
    }
}
/^Export configuration:/ { sub(/:.*/,""); name=$0; inEC=1 }

!inEC {
    name = value = $0
    sub(/[[:space:]]*:.*/,"",name)
    sub(/[^:]+:[[:space:]]+/,"",value)
    n2v[name] = value
}

END { prtRec() }

function prtRec() {
    print n2v["EVS"], n2v["EVS ID"], n2v["Export name"], n2v["Export path"], \
          n2v["File system label"], n2v["Export configuration"]
}

$ awk -f tst.awk file
58;EVSTEST1:;/EXPORT1;/opt/export1;fs_test1;-
59;EVSNEXT:;/next;/next;fs_next;10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash);10.26.xx.xx(rw,norootsquash)

Upvotes: 2

Related Questions