Compare files to get string before special character - bash

I am trying to evaluate two different files (.tf files) to check if the resource names are the same in a bash script.
I know that in those files resources are declared as such:
resource "service_name" "resource_name" {
#resource config
}
One approach would be something like:
while read line
do
if word_file1 == "resource"; then
#save string in array1 before "{" character
fi
while read line
do
if word_file2 == "resource"; then
#save string in array2 before "{" character
if array1 == array2; then
break
else
# write diff to another file, including all config
# info between {} for the missing or different resource
fi
fi
done < filename2
done < filename1
From a test file (file1) an example input would be:
resource "service_name" "resource_name_AA" {
#resource config
# policy_config = << POLICY
{
policy_definition
} POLICY
}
From a test file (file2) an example input would be:
resource "service_name" "resource_name_AA" {
#resource config
# policy_config = << POLICY
{
policy_definition
} POLICY
}
resource "service_name" "resource_name_BB" {
#resource config
# policy_config = << POLICY
{
policy_definition
} POLICY
}
The desired output would be (diff_file):
resource "service_name" "resource_name_BB" {
#resource config
# policy_config = << POLICY
{
policy_definition
} POLICY
}

I think I would try to keep it simpler than that:
grep 'resource' file1 > file1_resources.txt
grep 'resource' file2 > file2_resources.txt
diff file{1,2}_resources.txt
if the word "resource" shows up in different contexts, then you could use a regexp grep instead:
egrep "resource.*\{" fileX

This might do the job. I guess as per the code you showed, the contents of the resource also need to to printed in cases of mismatch. If only difference needs to be pointed out, diff is better and enough. Anyways I still like writing awk(still a bit new, learning) scripts, so wrote one.
#! /bin/bash
awk '{
if (FNR == NR)
{
if ($1 == "resource")
resource_name=$3
else
contents[resource_name]=contents[resource_name]"\n"
contents[resource_name]=contents[resource_name]$0
}
else
{
if (($1 == "}") && (flag == 1))
{
flag=0
next
}
else
if (($1 == "resource") && (contents[$3] != ""))
{
flag=1
contents[$3]=""
next
}
if (flag == 1)
next
print
}
}
END {
for (resource in contents)
{
if (contents[resource] != "")
print contents[resource]
}
}
' file2 file1 > otherfile
UPDATE:
#! /bin/bash
awk '{
if (FNR == NR)
{
if ($1 == "resource")
resource_name=$3
else
contents[resource_name]=contents[resource_name]"\n"
contents[resource_name]=contents[resource_name]$0
}
else
{
if (($1 == "}") && (flag == 1))
{
flag=0
next
}
else
if (($1 == "resource") && (contents[$3] == ""))
{
flag=1
contents[$3]=""
next
}
if (flag == 1)
next
print
}
}' file1 file2 > same_resources
UPDATE-2:
#! /bin/bash
awk '{
if (FNR == NR)
{
if ($1 == "resource")
resource_name=$3
else
contents[resource_name]=contents[resource_name]"\n"
contents[resource_name]=contents[resource_name]$0
}
else
{
if ($1 == "resource")
{
if (flag == 1)
{
flag=0
}
if (contents[$3] != "")
{
flag=1
contents[$3]=""
}
}
if (flag == 1)
next
print
}
}
END {
for (resource in contents)
{
if (contents[resource] != "")
print contents[resource]
}
}' file2 file1 > someotherfile

Related

Validate log file using shell

I want to validate a log file based on a reference file, I worked on a script but, it is not beautiful and is not optimal:
For each line I want to check the value of the fields,
- the field 7 equal to 1 I have to check columns 16 and 17
- the field 7 equal to 2 I have to check columns 25 and 27 and 30
- the field 7 equal to 3 I have to check columns 18 and 24 and 31
etc..
#!/bin/bash
LOG=SMS.log
awk -F\| ' {s=""}
$4!=0 {printf "API has wrong value"; s="; " }
$8=="" { printf "%sApplicationID is empty", s; s="; " }
$9=="" { printf "%shttp request method is empty", s; s="; " }
$7=="" { printf "%sOperationID is empty", s; s="; " }
$13 !~ /0|1|2/ {printf "%sresult(0,1,2) has a wrong value", s; s="; " }
# 1:create SMS
$7=="1" && $18=="" {printf "%sSender is missing", s; s="; " }
$7=="1" && $18 ~ /\/tel\:\+\*\*/ {printf "%sSender is cyphred !", s; s="; " }
$7=="1" && $20=="" {printf "%sAddress is missing", s; s="; " }
$7=="1" && $20 ~ /\/tel\:\+[0-9]/ {printf "%sAddress(es) is not cyphred", s; s="; " }
$7=="1" && $10 ~ /\/tel\:\+\*\*/ {printf "%sSender is cyphred on URI !", s; s="; " }
## 2:subscribe
$7=="2" && $25=="" {printf "%sdestination is missing", s; s="; " }
$7=="2" && $16=="201" && $27="" {printf "%sresourceId is missing", s; s="; "}
#3:unsubscribe
$7=="2" && $16=="201" && $25="" {printf "%sresource is missing", s; s="; "}
s { printf "\n"}
s
{printf "\n"}
' $LOG
Is it possible to update the code to be more optimal and beautiful.
Output:
Application is empty; Operation is empty; Http request method is empty
83ac|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:42.758Z|8|0|||||XXXXX|||||||||789|||||||||5945548f|||||
I'd do it like this:
awk -F'|' '
##### Error Detection
$4 != 0 { prtErr("ApiWrong") }
$8 == "" { prtErr("AppIdEmpty") }
$9 == "" { prtErr("HttpEmpty") }
$7 == "" { prtErr("OpIdEmpty") }
$13 !~ /[012]/ { prtErr("RsltBad") }
$7 == 1 { # 1:create SMS
if ( $18 == "" ) { prtErr("SndMiss") }
if ( $18 ~ /\/tel:\+\*\*/ ) { prtErr("SndCyph") }
if ( $20 == "" ) { prtErr("AddrMiss") }
if ( $20 ~ /\/tel:\+[0-9]/ ) { prtErr("AddrNotCyph") }
if ( $10 ~ /\/tel:\+\*\*/ ) { prtErr("SndCyphUri") }
}
$7 == 2 { # 2:subscribe
if ( $25 == "" ) { prtErr("DestMiss") }
if ( $16=="201" && $27=="" ) { prtErr("RsrcIdMiss") }
}
$7 == 3 { # 3:unsubscribe
if ( $16=="201" && $25=="" ) { prtErr("RsrcMiss") }
}
##### Error Reporting
function prtDbg(code,str) { if (doDebug) prtMsg("DEBUG",code,str) }
function prtTrc(code,str) { if (doTrace) prtMsg("TRACE",code,str) }
function prtWrn(code,str) { prtMsg("WARNING",code,str) }
function prtErr(code,str) { prtMsg("ERROR",code,str) }
function prtMsg(level, code, str, map, msg) {
map["ApiWrong"] = "API has wrong value"
map["AppIdEmpty"] = "ApplicationID is empty"
map["HttpEmpty"] = "http request method is empty"
map["OpIdEmpty"] = "OperationID is empty"
map["RsltBad"] = "result(0,1,2) has a wrong value"
map["SndMiss"] = "Sender is missing"
map["SndCyph"] = "Sender is cyphred !"
map["AddrMiss"] = "Address is missing"
map["AddrNotCyph" = "Address(es) is not cyphred"
map["SndCyphUri"] = "Sender is cyphred on URI !"
map["DestMiss"] = "destination is missing"
map["RsrcIdMiss"] = "resourceId is missing"
map["RsrcMiss"] = "resource is missing"
map["default"] = "Unknown error code"
msg = (code in map ? map[code] : map["default"])
printf "%s: %s[%d]: (%s) %s\n", level, FILENAME, FNR, code, msg | "cat>&2"
if ( str != "" ) {
printf "%s: %s[%d]:\t%s\n", $0 | "cat>&2"
}
}
' "$log"
That decouples the text being printed from the error indication and centralizes/instruments all error messages for a common look/feel and ability to add extra info if necessary and to de-clutter the code that's detecting the errors. I also showed how to separate errors, from warnings, etc. (you choose which is which in your code) and add tracing/debugging functions that you can all over the code if you like but to and they won't do anything till you set the relevant "do..." flag on the command line.
Update to just produce the specific output you asked for (untested):
BEGIN { FS="|" }
##### General processing including error detection
$4 != 0 { logErr("ApiWrong") }
$8 == "" { logErr("AppIdEmpty") }
$9 == "" { logErr("HttpEmpty") }
$7 == "" { logErr("OpIdEmpty") }
$13 !~ /[012]/ { logErr("RsltBad") }
$7 == 1 { # 1:create SMS
if ( $18 == "" ) { logErr("SndMiss") }
if ( $18 ~ /\/tel:\+\*\*/ ) { logErr("SndCyph") }
if ( $20 == "" ) { logErr("AddrMiss") }
if ( $20 ~ /\/tel:\+[0-9]/ ) { logErr("AddrNotCyph") }
if ( $10 ~ /\/tel:\+\*\*/ ) { logErr("SndCyphUri") }
}
$7 == 2 { # 2:subscribe
if ( $25 == "" ) { logErr("DestMiss") }
if ( $16=="201" && $27=="" ) { logErr("RsrcIdMiss") }
}
$7 == 3 { # 3:unsubscribe
if ( $16=="201" && $25=="" ) { logErr("RsrcMiss") }
}
{ prtErrs() }
##### Error reporting primitives
function logErr(code) { _errs[code] }
function prtErrs( code, map, msg, gotErrs, sep) {
for (code in _errs) {
gotErrs = 1
break
}
if (gotErrs) {
map["ApiWrong"] = "API has wrong value"
map["AppIdEmpty"] = "ApplicationID is empty"
map["HttpEmpty"] = "http request method is empty"
map["OpIdEmpty"] = "OperationID is empty"
map["RsltBad"] = "result(0,1,2) has a wrong value"
map["SndMiss"] = "Sender is missing"
map["SndCyph"] = "Sender is cyphred !"
map["AddrMiss"] = "Address is missing"
map["AddrNotCyph"] = "Address(es) is not cyphred"
map["SndCyphUri"] = "Sender is cyphred on URI !"
map["DestMiss"] = "destination is missing"
map["RsrcIdMiss"] = "resourceId is missing"
map["RsrcMiss"] = "resource is missing"
printf "%s: %s[%d]: ", "ERROR", FILENAME, FNR | "cat>&2"
for (code in _errs) {
msg = (code in map ? map[code] : "Unknown error code (" code ")")
printf "%s%s", sep, msg | "cat>&2"
sep = "; "
}
printf "\n%s\n", $0 | "cat>&2"
delete _errs
}
}
and if you have GNU awk for arrays of arrays and length(array) then I'd do it as:
BEGIN { FS="|" }
##### General processing including error detection
$4 != 0 { logErr("Wrong","API") }
$8 == "" { logErr("Empty","AppId") }
$9 == "" { logErr("Empty","Http request method") }
$7 == "" { logErr("Empty","OperationID") }
$13 !~ /[012]/ { logErr("Wrong","Result(0,1,2)") }
$7 == 1 { # 1:create SMS
if ( $18 == "" ) { logErr("Miss","Sender") }
if ( $18 ~ /\/tel:\+\*\*/ ) { logErr("Cyph","Sender") }
if ( $20 == "" ) { logErr("Miss","Address") }
if ( $20 ~ /\/tel:\+[0-9]/ ) { logErr("NotCyph","Address(es)") }
if ( $10 ~ /\/tel:\+\*\*/ ) { logErr("UriCyph","Sender") }
}
$7 == 2 { # 2:subscribe
if ( $25 == "" ) { logErr("Miss","Destination") }
if ( $16=="201" && $27=="" ) { logErr("Miss","ResourceId") }
}
$7 == 3 { # 3:unsubscribe
if ( $16=="201" && $25=="" ) { logErr("Miss","Resource") }
}
{ prtErrs() }
##### Error reporting primitives
function logErr(type,item) { _errs[type][item] }
function prtErrs( map, type, msg, item, sep) {
if ( length(_errs) ) {
map["Wrong"] = "has wrong value"
map["Empty"] = "is empty"
map["Miss"] = "is missing"
map["Cyph"] = "is cyphred !"
map["NotCyph"] = "is not cyphred"
map["UriCyph"] = "is cyphred on URI !"
printf "%s: %s[%d]: ", "ERROR", FILENAME, FNR | "cat>&2"
for (type in _errs) {
msg = (type in map ? map[type] : "Unknown error type (" type ")")
for (item in _errs[type]) {
printf "%s%s %s", sep, item, msg | "cat>&2"
sep = "; "
}
}
printf "\n%s\n", $0 | "cat>&2"
delete _errs
}
}
First thing you could do is get rid of the s variable.
#!/bin/bash
LOG=SMS.log
awk -F\| '
function add_error(message){
error = error OFS message
}
$4!=0 {add_error("API has wrong value")}
$8=="" {add_error("ApplicationID is empty")}
$9=="" {add_error("http request method is empty")}
$7=="" {add_error("OperationID is empty")}
$13 !~ /0|1|2/ {add_error("result(0,1,2) has a wrong value")}
# 1:create SMS
$7=="1" && $18=="" {add_error("Sender is missing")}
$7=="1" && $18 ~ /\/tel\:\+\*\*/ {add_error("Sender is cyphred !")}
$7=="1" && $20=="" {add_error("Address is missing")}
$7=="1" && $20 ~ /\/tel\:\+[0-9]/ {add_error("Address(es) is not cyphred")}
$7=="1" && $10 ~ /\/tel\:\+\*\*/ {add_error("Sender is cyphred on URI !")}
## 2:subscribe
$7=="2" && $25=="" {add_error("destination is missing")}
$7=="2" && $16=="201" && $27="" {add_error("resourceId is missing")}
#3:unsubscribe
$7=="2" && $16=="201" && $25="" {add_error("resource is missing")}
{
print substr(error, length(OFS)+1); #Works even if error is empty
error = "";
}
' OFS="; " $LOG
I think that it is a bit strange to analyze your log file and create ... a new log file. Why don't you create a csv with 1 column per error and 1/0 values for each line/error ? Your result would be much more easier to analyze and would contains all the informations you need.

Reading 3 Delimited Files passed as Parameters to a AWK Script and parse the 3 Files and store in 3 different arrays

File 1:
A|sam|2456|8901
B|kam|5678|9000
C|pot|4567|8000
File 2:
X|ter|2456|8901
Y|mar|5678|9000
Z|poi|4567|8000
File 3:
Column1|Column2|Column3|Coumn4
Now i want this 3 Files to be passed as parameters to the GNU Awk Script as below -
awk -f script.awk file1 file2 file3
Script i have written are able to handle only 2 Files but not able to handle the 3rd file. Pleas help.
script.awk
BEGIN { # setup file separator and sorting:
FS=OFS="|"
PROCINFO["sorted_in"]="#ind_str_asc"
}
# skip header lines
FNR == 1 { next }
# store first file
(FNR==NR) { f1[$5]=$0
# skip processing of other rules and
# read the next line from input
next
}
# store second file
{ f2[$5]=$0
if( ! ($5 in f1)) {
f1[$5] = ""
}
}
END {
for( k in f1) {
split( f1[k], arr1, "|")
for( c = 1; c <= length( f1[ k ] ); c++ ) {
print arr1[c]
}
}
for( k in f2) {
split( f2[k], arr2, "|")
for( c = 1; c <= length( f2[ k ] ); c++ ) {
print arr2[c]
}
}
}
}
My Objective is the Read the 3rd File also in the same code in the print in the similar way as the printing is handled in the above code.
Note : Would be good if anyone can keep the similar Code structure as above and just include the reading and printing of the 3rd File.
Your existing code is more complicated than it has to be. It could be written as just:
BEGIN { # setup file separator and sorting:
...
}
# skip header lines
FNR == 1 { next }
ARGIND==1 { f1[$5]=$0; next }
ARGIND==2 { f2[$5]=$0; f1[$5] }
END {
...
}
I assume you can see the obvious extension to add a 3rd file. The above requires GNU awk for ARGIND and PROCINFO[] which you're already using.
You can use ARGV array to process multiple files like this:
function disp() {
for (i=1; i<=NF; i++)
print FILENAME " :: " FNR " :: " $i
print ""
}
BEGIN { # setup file separator and sorting:
FS=OFS="|"
PROCINFO["sorted_in"]="#ind_str_asc"
}
# process first file
ARGV[1] == FILENAME {
disp()
}
# process second file
ARGV[2] == FILENAME {
disp()
}
# process third file
ARGV[3] == FILENAME {
disp()
}

Need Algorithm to create a auto code from a CSV file

I have "N" columns in a csv file say Hardware,Sensors,Statistics(1,2,3 .....N) as shown below.
Each column has unique xml code that I need to generate with respect to the above table content.
<Hardware A>
<Sensors sen1>
<Stat1>Mean</Stat1>
<Stat2>Avg</Stat2>
<Stat3>Slope</Stat3>
</Sensors sen1>
<Sensors sen2>
<Stat1>Min</Stat1>
<Stat2>Max</Stat2>
<Stat3>Mean</Stat3>
</Sensors sen2>
....
....
</Hardware A>
I need to generate a code similar to above with respect to the table. Can anybody tell an Algorithm to implement this structure using SHELL SCRIPT
It'd be something like this in awk (untested obviously since you didn't provide testable sample input/output):
BEGIN { FS=","; fmt="%s %s>\n" }
NR==1 {
for (i=1;i<=NF;i++) {
tagName[i] = $i
}
next
}
$1 != "" {
if (prev != "") {
printf "</"fmt, tagName[1], prev
}
printf "<"fmt, tagName[1], $1
prev = $1
}
{
printf " <"fmt, tagName[2], $2
for (i=3;i<=NF;i++) {
printf " <%s>%s</%s>\n", tagName[i], $i, tagName[i]
}
printf " </"fmt, tagName[2], $2
}
END {
if (prev != "") {
printf "</"fmt, tagName[1], prev
}
}

Parsing iw wlan0 scan output

I wrote wlan manager script to handle open/ad-hoc/wep/wpa2 networks. Now im trying to parse iw wlan0 scan output to get nice scan feature to my script. My goal is to get output like this :
SSID channel signal encryption
wlan-ap 6 70% wpa2-psk
test 1 55% wep
What i have achived already is output like this :
$ iw wlan0 scan | grep 'SSID\|freq\|signal\|capability' | tac
SSID: Koti783
signal: -82.00 dBm
capability: ESS Privacy ShortPreamble SpectrumMgmt ShortSlotTime (0x0531)
freq: 2437
I have been trying to study bash/sed/awk but havent found yet a way to achieve what im trying. So what is good way to achieve that?
Here is my final solution based of Sudo_O answer:
$1 == "BSS" {
MAC = $2
wifi[MAC]["enc"] = "Open"
}
$1 == "SSID:" {
wifi[MAC]["SSID"] = $2
}
$1 == "freq:" {
wifi[MAC]["freq"] = $NF
}
$1 == "signal:" {
wifi[MAC]["sig"] = $2 " " $3
}
$1 == "WPA:" {
wifi[MAC]["enc"] = "WPA"
}
$1 == "WEP:" {
wifi[MAC]["enc"] = "WEP"
}
END {
printf "%s\t\t%s\t%s\t\t%s\n","SSID","Frequency","Signal","Encryption"
for (w in wifi) {
printf "%s\t\t%s\t\t%s\t%s\n",wifi[w]["SSID"],wifi[w]["freq"],wifi[w]["sig"],wifi[w]["enc"]
}
}'
Output:
$ sudo iw wlan0 scan | awk -f scan.awk
SSID Frequency Signal Encryption
netti 2437 -31.00 dBm Open
Koti783 2437 -84.00 dBm WPA
WLAN-AP 2462 -85.00 dBm WPA
it's generally bad practice to try parsing complex output of programs intended for humans to read (rather than machines to parse).
e.g. the output of iw might change depending on the language settings of the system and/or the version of iw, leaving you with a "manager" that only works on your development machine.
instead you might use the same interface that iw uses to get it's information: the library backend libnl
you might also want to have a look at the wireless-tools (iwconfig, iwlist,...) that use the libiw library.
Here is an GNU awk script to get you going that grabs the SSIDs and the channel for each unique BSS:
/^BSS / {
MAC = $2
}
/SSID/ {
wifi[MAC]["SSID"] = $2
}
/primary channel/ {
wifi[MAC]["channel"] = $NF
}
# Insert new block here
END {
printf "%s\t\t%s\n","SSID","channel"
for (w in wifi) {
printf "%s\t\t%s\n",wifi[w]["SSID"],wifi[w]["channel"]
}
}
It should be easy for you to add the new blocks for signal and encryption considering all the studying you have been doing.
Save the script to file such as wifi.awk and run like:
$ sudo iw wlan0 scan | awk -f wifi.awk
The output will be in the formatted requested:
SSID channel
wlan-ap 6
test 1
Here is a simple Bash function which uses exclusively Bash internals and spawns only one sub-shell:
#!/bin/bash
function iwScan() {
# disable globbing to avoid surprises
set -o noglob
# make temporary variables local to our function
local AP S
# read stdin of the function into AP variable
while read -r AP; do
## print lines only containing needed fields
[[ "${AP//'SSID: '*}" == '' ]] && printf '%b' "${AP/'SSID: '}\n"
[[ "${AP//'signal: '*}" == '' ]] && ( S=( ${AP/'signal: '} ); printf '%b' "${S[0]},";)
done
set +o noglob
}
iwScan <<< "$(iw wlan0 scan)"
Output:
-66.00,FRITZ!Box 7312
-56.00,ALICE-WLAN01
-78.00,o2-WLAN93
-78.00,EasyBox-7A2302
-62.00,dlink
-74.00,EasyBox-59DF56
-76.00,BELAYS_Network
-82.00,o2-WLAN20
-82.00,BPPvM
The function can be easily modified to provide additional fields by adding a necessary filter into the while read -r AP while-loop, eg:
[[ "${AP//'last seen: '*}" == '' ]] && ( S=( ${AP/'last seen: '} ); printf '%b' "${S[0]},";)
Output:
-64.00,1000,FRITZ!Box 7312
-54.00,492,ALICE-WLAN01
-76.00,2588,o2-WLAN93
-78.00,652,LN8-Gast
-72.00,2916,WHITE-BOX
-66.00,288,ALICE-WLAN
-78.00,800,EasyBox-59DF56
-80.00,720,EasyBox-7A2302
-84.00,596,ALICE-WLAN08
I am using such solution for openwrt:
wlan_scan.sh
#!/bin/sh
sudo iw dev wlan0 scan | awk -f wlan_scan.awk | sort
wlan_scan.awk
/^BSS/ {
mac = gensub ( /^BSS[[:space:]]*([0-9a-fA-F:]+).*?$/, "\\1", "g", $0 );
}
/^[[:space:]]*signal:/ {
signal = gensub ( /^[[:space:]]*signal:[[:space:]]*(\-?[0-9.]+).*?$/, "\\1", "g", $0 );
}
/^[[:space:]]*SSID:/ {
ssid = gensub ( /^[[:space:]]*SSID:[[:space:]]*([^\n]*).*?$/, "\\1", "g", $0 );
printf ( "%s %s %s\n", signal, mac, ssid );
}
result
-62.00 c8:64:c7:54:d9:05 a
-72.00 70:72:3c:1c:af:17 b
-81.00 78:f5:fd:be:33:cb c
There is a bug in the awk script above.
The following code will not work if the SSID has spaces in the name. The received result will be the first token of the SSID name only.
$1 == "SSID:" {
wifi[MAC]["SSID"] = $2
}
When printing $0, $1, $2:
$0: SSID: DIRECT-82-HP OfficeJet 8700
$1: SSID:
$2: DIRECT-82-HP
One possibly solution is to take a substr of $0 which contains leading spaces, the token "SSID: " and the provided multi-token network name.
Any other suggestions?
I've taken awk code from Ari Malinen and reworked it a bit, because iw output is not stable and changes, also there are other issues like spaces in SSID. I put it on github in case if I'll change it in the future.
#!/usr/bin/env awk -f
$1 ~ /^BSS/ {
if($2 !~ /Load:/) { #< Escape "BBS Load:" line
gsub("(\\(.*|:)", "", $2)
MAC = toupper($2)
wifi[MAC]["enc"] = "OPEN"
wifi[MAC]["WPS"] = "no"
wifi[MAC]["wpa1"] = ""
wifi[MAC]["wpa2"] = ""
wifi[MAC]["wep"] = ""
}
}
$1 == "SSID:" {
# Workaround spaces in SSID
FS=":" #< Changing field separator on ":", it should be
# forbidded sign for SSID name
$0=$0
sub(" ", "", $2) #< remove first whitespace
wifi[MAC]["SSID"] = $2
FS=" "
$0=$0
}
$1 == "capability:" {
for(i=2; i<=NF; i++) {
if($i ~ /0x[0-9]{4}/) {
gsub("(\\(|\\))", "", $i)
if (and(strtonum($i), 0x10))
wifi[MAC]["wep"] = "WEP"
}
}
}
$1 == "WPA:" {
wifi[MAC]["wpa1"] = "WPA1"
}
$1 == "RSN:" {
wifi[MAC]["wpa2"] = "WPA2"
}
$1 == "WPS:" {
wifi[MAC]["WPS"] = "yes"
}
$1 == "DS" {
wifi[MAC]["Ch"] = $5
}
$1 == "signal:" {
match($2, /-([0-9]{2})\.00/, m)
wifi[MAC]["Sig"] = m[1]
}
$1 == "TSF:" {
gsub("(\\(|d|,)", "", $4)
match($5, /([0-9]{2}):([0-9]{2}):/, m)
day = $4
hour = m[1]
min = m[2]
wifi[MAC]["TSF"] = day"d"hour"h"min"m"
}
END {
for (w in wifi) {
if (wifi[w]["wep"]) {
if (wifi[w]["wpa1"] || wifi[w]["wpa2"])
wifi[w]["enc"] = wifi[w]["wpa1"]wifi[w]["wpa2"]
else
wifi[w]["enc"] = "WEP"
}
printf "%s:%s:%s:%s:%s:%s:%s\n", w, wifi[w]["SSID"], wifi[w]["enc"], \
wifi[w]["WPS"], wifi[w]["Ch"], wifi[w]["Sig"], wifi[w]["TSF"]
}
}
Output:
A5FEF2C499BB:test-ssid2:OPEN:no:9:43:0d00h00m
039EFACA9A8B:test-ssid2:WPA1:no:9:33:0d00h00m
038BF3C1988B:test-ssid2:WPA2:no:9:35:0d00h00m
028EF3C2997B:test-ssid2:WPA1:no:9:35:0d00h03m
if you wonder what if($2 !~ /Load:/) does, well on some routers there might be "BSS Load:" string.

Parsing error in awk [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Parsing errors in awk blocks
I am getting a parsing error while executing an awk script. I am not sure abt this. Here is the script
`awk 'BEGIN
{
INPUTFILE ='XXX'; iterator =0;
requestIterator =0;
storageFlag =T;
printFlag =F;
currentIteration =F;
recordCount =1;
while (getline < "'"$INPUTFILE"'")
{
requestArray[requestIterator]++;
requestIterator++;
}
}
if ($1 ~ /RequestId/)
{
FS = "=";
if($2 in requestArray)
{
storage[iterator] =$0;
printFlag =T;
next
}
else
{
storageFlag =F;
next
}
}
else
{
if((storageFlag =='T' && $0 != "EOE"))
{
storage[iterator]=$0; iterator++;
}
else {if(storageFlag == 'F')
{
next
}
else
{
if(printFlag == 'T')
{
for(details in storage)
{
print storage[details] >> FILE1;
delete storage[details];
}
printFlag =F;
storageFlag =T;
next
}
}
}
}' FILE2`
Error
zsh: parse error near `}'
Could you ppl please let me know whats wrong in this script
Your parens are mismatched (13 x { vs 12 x }), so you are missing a final closing } at the end of your script.
I.e.,
next}}}}' FILE2
should be
next}}}}}' FILE2

Resources