Reputation: 181
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
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
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