Validate log file using shell - 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.

Related

Edit certain variables in a file using bash script

Below i have the following SES.ses file:
1 VERSION_CONTROL {
2 FILE_NAME = "C:/Users/kjbaili/Documents/SWCD_TEST/SES.ses";
3 DATE = "";
4 VERSION = "1.1";
5 AUTHOR = "";
6 }
7
8 DISPLAYS {
9 DISPLAY xxx-c-vm-0120:main = {
10 COMPUTER = "xxx-C-VM-0120";
11 DISPLAY = "main";
12 ITEMS {
13 PANEL {
14 name = "visu.pnl";
15 }
16 }
17 }
18 }
19
20 RT-HOSTS {
21 RT-HOST xxx-c-vm-0120 = {
22 COMPONENT {
23 name = "RTE_connections_xxxxx.cmp";
24 }
25 COMPONENT {
26 name = "xxxx.cmp";
27 }
28 }
29 RT-HOST xxx-c-agx-0003 = {
30 COMPONENT {
31 name = "CtApxxx.cmp";
32 }
33 COMPONENT {
34 name = "CtApxxx.cmp";
35 }
36 COMPONENT {
37 name = "CtApxxx.cmp";
38 }
39 }
40 }
41
42 HARDWARE {
43 }
The user enters three Inputs to be placed in lines 2, 9, 21 and 29 -> /userpath, DISPLAY Node0, RT-HOSTS Node0, and RT-HOSTS Node1 accordingly.
I'm trying to edit variables in this file based on above user's input. These are : FILE_NAME (line 2), DISPLAY (line 9), RT-HOSTS ( line 21 and 29)
After doing some research i could build the following:
currentPath=$(pwd)/SES
awk -v path="$currentPath" '/FILE_NAME/ {cnt++} /FILE_NAME/ && cnt==1 {lnee=gensub(/(^.*\")(.*)(\".*$)/,"\\1"path"\\3",$0);print lnee; next}1' SES.ses > SES.temp && mv -f SES.tmp SES.ses
This command supposes to find the first entry for FILE_NAME and set the variable currentPath to it. However i'm getting the following error:
awk: cmd. line:1: warning: regexp escape sequence `\"' is not a known regexp operator
mv: cannot stat 'SES.tmp': No such file or directory
So my question is how to solve this error and how to set the other three variables line 9, 21 and 29
Thank in advance and would really appriciate your help
suggested solution from #Ed Morton:
awk -v filename='foo' -v display='bar' -v rthosts='some others' 'BEGIN { numRth = split(rthosts,rths) }
(filename != "") && ($1 == "FILE_NAME") { newval=filename; filename="" }
(display != "") && ($1 == "DISPLAY") { newval=display; display="" }
(numRth in rths) && ($1 == "RT-HOST") { newval=rths[++c]; delete rths[c] }
newval != "" {
oldval = ( $2 == "=" ? $3 : $2 )
gsub(/^[^"]*"|"[^"]*$/,"",oldval)
pos = index($0,oldval)
$0 = substr($0,1,pos-1) newval substr($0,pos+length(oldval))
newval = ""
}
{ print }' SES.ses
output of cat -Ev SES.ses
$
VERSION_CONTROL {$
FILE_NAME = "/c/Users/kjbaili/Documents/DO_NOT_DELETE/SES";$
DATE = "";$
VERSION = "1.1";$
AUTHOR = "";$
}$
$
DISPLAYS {$
DISPLAY d = {$
COMPUTER = "FDT-C-VM-0120";$
DISPLAY = "main";$
ITEMS {$
PANEL {$
name = "visu.pnl";$
}$
}$
}$
}$
$
RT-HOSTS {$
RT-HOST v = {$
COMPONENT {$
name = "RTE_connections_CtCoFallbackPath.cmp";$
}$
COMPONENT {$
name = "CtGwHwpFbpCmp.cmp";$
}$
}$
RT-HOST v = {$
COMPONENT {$
name = "CtApHwpFbpSit.cmp";$
}$
COMPONENT {$
name = "CtApHwpFbpMpl.cmp";$
}$
COMPONENT {$
name = "CtApHwpFbpCVGen.cmp";$
}$
}$
}$
$
HARDWARE {$
}$
The 3rd argument to the gensub() function must be a count of replacement
such as 1 or g (global).
Would you please try instead:
#!/bin/bash
# user's inputs
read -p "FILE_NAME: " -r file_name
read -p "DISPLAY: " -r display
read -p "RT-HOST: " -r rt_host
awk -v file_name="$file_name" -v display="$display" -v rt_host="$rt_host" '
{
sub(/FILE_NAME *= *\"[^"]+/, "FILE_NAME = \"" file_name)
sub(/DISPLAY *[^:]+:/, "DISPLAY " display ":")
}
/RT-HOST / {
if (! count++)
sub(/RT-HOST *[^[:space:]]+ *=/, "RT-HOST " display " =")
else
sub(/RT-HOST *[^[:space:]]+ *=/, "RT-HOST " rt_host " =")
}
1
' SES.ses > SES.tmp && mv -f -- SES.tmp SES.ses
You're getting the warning (not error) message escape sequence '\"' is not a known regexp operator because " isn't a regexp metachar, it's just a plain old literal char like x, but in your regexp (^.*\")(.*)(\".*$) you've written \" so either:
you're trying to escape " when it doesn't need to be escaped
or,
you're trying to include a literal \ in your regexp but
you'd need to escape it as \\ to do that.
So either way something is wrong with your regexp so awk is warning you about it.
I THINK this is probably what you're trying to do:
$ cat tst.awk
BEGIN { numRth = split(rthosts,rths) }
(filename != "") && ($1 == "FILE_NAME") { newval=filename; filename="" }
(display != "") && ($1 == "DISPLAY") { newval=display; display="" }
(numRth in rths) && ($1 == "RT-HOST") { newval=rths[++c]; delete rths[c] }
newval != "" {
oldval = ( $2 == "=" ? $3 : $2 )
gsub(/^[^"]*"|"[^"]*$/,"",oldval)
pos = index($0,oldval)
$0 = substr($0,1,pos-1) newval substr($0,pos+length(oldval))
newval = ""
}
{ print }
$ awk -v filename='foo' -v display='bar' -v rthosts='some others' -f tst.awk file
VERSION_CONTROL {
FILE_NAME = "foo";
DATE = "";
VERSION = "1.1";
AUTHOR = "";
}
DISPLAYS {
DISPLAY bar = {
COMPUTER = "xxx-C-VM-0120";
DISPLAY = "main";
ITEMS {
PANEL {
name = "visu.pnl";
}
}
}
}
RT-HOSTS {
RT-HOST some = {
COMPONENT {
name = "RTE_connections_xxxxx.cmp";
}
COMPONENT {
name = "xxxx.cmp";
}
}
RT-HOST others = {
COMPONENT {
name = "CtApxxx.cmp";
}
COMPONENT {
name = "CtApxxx.cmp";
}
COMPONENT {
name = "CtApxxx.cmp";
}
}
}
HARDWARE {
}
If ed is available/acceptable.
This should show the replacement.
#!/usr/bin/env bash
file_name=foobar
display=barmore
rt_host=quxfux
ed -s SES.ses <<-EOF
2,/FILE_NAME/s/".\{1,\}"/"$file_name"/
9s|^\([[:blank:]]*DISPLAY\).\{1,\}\(=[[:blank:]]*{\$\)|\1 $display \2|
21,29s|^\([[:blank:]]*RT-HOST\).\{1,\}\(=[[:blank:]]*{\$\)|\1 $rt_host \2|
,p
Q
EOF
Just like what #tshiono did using the builtin read to get the user's input
#!/usr/bin/env bash
# user's inputs
read -p "FILE_NAME: " file_name
read -p "DISPLAY: " display
read -p "RT-HOST: " rt_host
ed -s SES.ses <<-EOF
2,/FILE_NAME/s/".\{1,\}"/"$file_name"/
9s|^\([[:blank:]]*DISPLAY\).\{1,\}\(=[[:blank:]]*{\$\)|\1 $display \2|
21,29s|^\([[:blank:]]*RT-HOST\).\{1,\}\(=[[:blank:]]*{\$\)|\1 $rt_host \2|
,p
Q
EOF
The ,p is there just show what is the output of the newly edited buffer, remove it to silence the output.
Change Q to w to edit the file-inplace

Compare files to get string before special character

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

Inputing variables to awk script

I am working on a script that detects CDP information from the network card. The script currently works on my computer, but i would like to make it available for other people. The script currently runs because in the code it has the name of my network card. I would like to make it ask for the network card name (perhaps list the ones available) before running the script. My code is:
#!/usr/bin/awk -f
function red(s) {
printf "\033[1;31m" s "\033[0m "
}
function green(s) {
printf "\033[1;32m" s "\033[0m "
}
function blue(s) {
printf "\033[1;34m" s "\033[0m "
}
BEGIN{
cmd = "tcpdump -nvi enp0s25 -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1"
while ((cmd | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")
for(i=1;i<=length(s);i++){
if ($0 ~ s[i] && s[i]){
if (i==1){
print "\n";
print red("Device Name: ") green($7);
}
else if (i==2){
print red("Software Version: ") green($0) ;
}
else if (i==3){ /*Port*/
print red($1 ": ") green($7);
}
else if (i==4){
print red($1 " " $2 " " $3 ": ") green($9);
}
else if (i==5){
print red("IP Address: ") green($9);
}
else if (i==6){
print red("VLAN: ") green($9);
}
else if (i==7){
print red("DUPLEX: ") green($7);
}
else if (i==8){
print red("Voice VLAN: ") green($13);
}
else{
s[i]=0;print " "}
}
}
}
}
As you can see, it runs the command with my NIC which is enp0s25. I need to make this a variable, that is entered by the user (maybe only once). the best approach would be to enumerate the cards and have the user pick the card he wants using a number. I have NO IDEA how to do this.
You're making life harder for youself by trying to use awk as a shell by encoding the call to tcpdump inside awk. Think about that - you're writing a shell script to call awk to call shell to call tcpdump instead of just having shell call tcpdump and pipe the output to awk.
Just write your shell script as:
tcpdump ... enp0s25 ... | awk 'script'
and then you can tweak it in the obvious way:
echo "enter a nic: "
IFS= read -r nic
tcpdump ... "$nic" ... | awk 'script'
#!/usr/bin/awk -f
function red(s) {
printf "\033[1;31m" s "\033[0m "
}
function green(s) {
printf "\033[1;32m" s "\033[0m "
}
function blue(s) {
printf "\033[1;34m" s "\033[0m "
}
function detectNic( ) {
printf "Enter the Ethernet card to listen or press enter to listen
to Default:";getline nic<"/dev/tty"
if (nic == ""){
command = "cat /var/defaultnic"
nic = command | getline
print "Default network card to listen: " $nic
return $nic
}
else{
return nic
}
}
BEGIN{
nic = detectNic();
cmd = "tcpdump -nv -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1 -i"
while ((cmd nic | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")
for(i=1;i<=length(s);i++){
if ($0 ~ s[i] && s[i]){
#DEVICE ID
if (i==1){
print "\n";
print red("Device Name: ") green($7);
}
#SOFTWARE VERSION
else if (i==2){
print red("Software Version: ") green($0) ;
}
#PORT
else if (i==3){
print red($1 ": ") green($7);
}
#VTP DOMAIN
else if (i==4){
print red($1 " " $2 " " $3 ": ") green($9);
}
#IP ADDRESS
else if (i==5){
print red("IP Address: ") green($9);
}
#CURRENT VLAN
else if (i==6){
print red("VLAN: ") green($9);
}
#DUPLEX
else if (i==7){
print red("DUPLEX: ") green($7);
}
#VOICE VLAN
else if (i==8){
print red("Voice VLAN: ") green($13);
}
else{
s[i]=0;print " "}
}
}
}
}

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 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