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
Related
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
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()
}
I have 200000 integers written in a file like this
0
1
2
3
.
98
99
.
.
100
101
102
.
I want to write with awk or join script that would tell how many times this pattern(from 0 to 99 )repeats itself.
Not battle tested:
awk 'i++!=$0{i=$0==0?1:0}i==100{c++;i=0}END{print c}' p.txt
Breakdown:
i++ != $0 { # Use a cursor (i) which will be compared to input
i=$0==0?1:0; # If not matched reset cursor if current line is zero then set to 1 because
# .. this means we already matched our first line. If not set to 0
i == 100 { # If Full pattern found:
c++; # add to count
i=0; # reset cursor
}
END {print c} # Print matched count
You can do this using a state variable which is reset anytime the pattern is incomplete. For example:
#!/usr/bin/awk -f
BEGIN {
state = -1;
count = 0;
}
/^[0-9]+$/ {
if ( $0 == ( state + 1 ) || $0 == 0 ) {
state = $0;
if ( state == 99 ) {
count++;
}
} else {
state = -1;
}
next;
}
{ state = -1; next; }
END {
print count;
}
This script assumes awk is in /usr/bin (the usual case). You would put the script in a file, e.g., "patterns", and run it like
./patterns < p.txt
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
}
}
In awk, how can I do this:
1303361997;15;67.067014
1303361997;5;51.529837
1303361997;14;47.036197
1303361997;3;44.064681
1303361997;6;37.632831
1303361997;23;24.990078
1303361997;24;26.750984
1303361998;15;67.074100
1303361998;5;51.522981
1303361998;14;47.028185
1303361998;3;44.056715
1303361998;6;37.638584
1303361998;23;24.987800
1303361998;24;26.756648
When number in second columns is absent this date should be replace by zero in output file.
First place is the number of the first column. The values of the second column of data to determine the position of the third column in the output file. The first column each time it may begin with different values. Desired output, by sorting first and second columns:
1303361997;0;0;44.064681;0;51.529837;37.632831;0;0;0;0;0;0;0;47.036197;67.067014;0;0;0;0;0;0;0;24.990078;26.750984;
1303361998;0;0;44.056715;0;51.522981;37.638584;0;0;0;0;0;0;0;47.028185;67.074100;0;0;0;0;0;0;0;24.987800;26.756648;
$ cat tst.awk
BEGIN { FS=";" }
NR == 1 {
for (i=1;i<=2;i++) {
min[i] = max[i] = $i
}
}
{
val[$1,$2] = $3
keys[$1]
for (i=1;i<=2;i++) {
min[i] = ($i < min[i] ? $i : min[i])
max[i] = ($i > max[i] ? $i : max[i])
}
}
END {
for (r=min[1];r<=max[1];r++) {
if (r in keys) {
printf "%d",r
for (c=1;c<=max[2];c++) {
printf ";%s", ((r,c) in val ? val[r,c] : 0)
}
print ";"
}
}
}
$
$ cat file
1303361997;15;67.067014
1303361997;5;51.529837
1303361997;14;47.036197
1303361997;3;44.064681
1303361997;6;37.632831
1303361997;23;24.990078
1303361997;24;26.750984
1303361998;15;67.074100
1303361998;5;51.522981
1303361998;14;47.028185
1303361998;3;44.056715
1303361998;6;37.638584
1303361998;23;24.987800
1303361998;24;26.756648
$
$ awk -f tst.awk file
1303361997;0;0;44.064681;0;51.529837;37.632831;0;0;0;0;0;0;0;47.036197;67.067014;0;0;0;0;0;0;0;24.990078;26.750984;
1303361998;0;0;44.056715;0;51.522981;37.638584;0;0;0;0;0;0;0;47.028185;67.074100;0;0;0;0;0;0;0;24.987800;26.756648;