How to write awk function - awk

I have a quick file file.awk with
function attr(attrname,str, a) {
if (!str) str=$0
match(str,"#" attrname "=([^,/]*)",a)
return a[1]
}
I am getting an error
awk: file.awk: line 139: syntax error at or near ,
where line 139 is the line with match()
Any idea whats wrong with the syntax?

You're trying to use the non-POSIX 3rd arg to match() but not using GNU awk which supports it. See https://www.gnu.org/software/gawk/manual/gawk.html#String-Functions.

As always, Ed Morton has it correct. The only reason I'm posting is that I can share with MacOS users that the awk man page includes the answer.
man awk yields:
match(s, r)
the position in s where the regular expression r occurs, or 0 if it does not. The variables RSTART and RLENGTH are set to the position and
length of the matched string.
So it is very clear that your call has an extra parameter.
I tried runnning awk with your function on MacOS and got this error:
awk: syntax error at source line 1 in function attr source file
context is
match(str,"#" attrname >>> "=([^,/]*)", <<<
The "<<<" is indicating awk doesn't like that comma. This is similar to your error message:
syntax error at or near ,

You absolutely don't need the match() function's capture array to get the attribute value you're seeking :
echo 'april#token=sha256hmackey/0.ts' \
\
| mawk 'function attr(___,_,__,____) { ____="\32\21"
if(_=="") {
_=$(_<_) }
return \
sub("[#]"(___)"=[^,\\/]*",____"&"____,_) \
\
? substr(_=__[split(_,__,____)-\
(_~_)],index(_,"=")+(_~"")) : ""
} {
print attr("token") }'
sha256hmackey

Related

Awk syntax error due to improper placement of the function definition

It is embarrassing, but could someone briefly explain why this gives syntax error?
echo why this fails? | gawk '{
function why(fail) {
print fail
}
why($0)
}'
The function definition has to be at the top level. You have it inside the {...}.
echo This works | gawk '
function why(fail) {
print fail
}
{
why($0)
}'

Trap or evaluate bad regular expression string at runtime in awk script

How can I trap an error if a dynamic regular expression evaluation is bad like:
var='lazy dog'
# a fixed Regex here, but original is coming from ouside the script
Regex='*.'
#try and failed
if (var ~ Regex) foo
The goal is to manage this error as I cannot test the regex itself (it comes from external source). Using POSIX awk (AIX)
Something like this?
$ echo 'foo' |
awk -v re='*.' '
BEGIN {
cmd="awk --posix \047/" re "/\047 2>&1"
cmd | getline rslt
print "rslt="rslt
close(cmd)
}
{ print "got " $0 " but re was bad" }
'
rslt=awk: cmd. line:1: error: Invalid preceding regular expression: /*./
got foo but re was bad
I use gawk so I had to add --posix to make it not just accept that regexp as a literal * followed by any char. You'll probably have to change the awk command being called in cmd to behave sensibly for your needs with both valid and invalid regexps but you get the idea - to do something like an eval in awk you need to have awk call itself via system() or a pipe to getline. Massage to suit...
Oh, and I don't think you can get the exit status of cmd with the above syntax and you can't capture the output of a system() call within awk so you may need to test the re twice - first with system() to find out if it fails but redirecting it's output to /dev/null, and then on a failure run it again with getline to capture the error message.
Something like:
awk -v re='*.' '
BEGIN {
cmd="awk --posix \047/" re "/\047 2>&1"
if ( system(cmd " > /dev/null") ) {
close(cmd " > /dev/null")
cmd | getline rslt
print "rslt="rslt
close(cmd)
}
}
{ print "got " $0 " but re was bad" }
'

AWK - Max Variables?

Why does the first statement work but not the second? I'm trying to add an additional two (one shown) variables to do another comparison, but the second instance errors out.
1st Instance
awk 'f1=substr($1,0,9), f2=substr($3,0,9){if(f1==f2)print $1,$2,$3,$4}' file
2nd Instance
awk 'f1=substr($1,0,9), f2=substr($3,0,9), f3=substr($1,5,3){if(f1==f2)print $1,$2,$3,$4}' file
awk: cmd. line:1: f1=substr($1,0,9), f2=substr($3,0,9), f3=substr($1,5,3){if(f1==f2)print $1,$2,$3,$4,16}
awk: cmd. line:1: ^ syntax error
File
TULSHDRJ02 ae0.0 KSCYBBRJ01 ae1.0
MTC3BBRJ02 ae4.0 KSCYBBRJ01 ae6.0
KSCYBBRJ01 ae2.0 KSCYBBRJ02 ae2.0
MTC1BBRJ02 ae4.0 KSCYBBRJ02 ae6.0
Output
KSCYBBRJ01 ae2.0 KSCYBBRJ02 ae2.0
$ awk 'substr($1,1,9)==substr($3,1,9){print $1,$2,$3,$4}' file
since you're printing everything you can drop the action part
$ awk 'substr($1,1,9)==substr($3,1,9)' file
or, for DRY
$ awk 'function s(v) {return substr(v,1,9)}
s($1)==s($3)' file
The general program structure of an awk program is as follows:
condition { action [; action [ ; ... ]] }
Multiple actions are separated by ; or newline.
Both the condition and the block of actions are optional. When you omit the condition
{ action [; action [ ; ... ]] }
... actions will be always executed. If you omit the actions:
condition
... the default action is print.
Multiple of those blocks can be put in a row:
cond1 { action1 } cond2 {action2} ...
Note: newline can be always used as a delimiter (for multiline programs)
I guess you wanted:
awk '{f1=substr($1,0,9);f2=substr($3,0,9)} f1==f2{print $1,$2,$3,$4}'
... or in multiline form:
awk '# Runs on every line
{
f1=substr($1,0,9)
f2=substr($3,0,9)
}
# Runs only if condition is met
f1==f2 {
print $1,$2,$3,$4
}'
But not quite!
It should be
awk '{f1=substr($1,1,9);f2=substr($3,1,9)} f1==f2{print $1,$2,$3,$4}'
instead of
awk '{f1=substr($1,0,9);f2=substr($3,0,9)} f1==f2{print $1,$2,$3,$4}'
Note that string, field and array indices in awk start at 1, not 0.
Please check also karakfa's answer, which shows how the command can be simplified.

awk: non-terminated string

I'm trying to run the command below, and its giving me the error. Thoughts on how to fix? I would rather have this be a one line command than a script.
grep "id\": \"http://room.event.assist.com/event/room/event/" failed_events.txt |
head -n1217 |
awk -F/ ' { print $7 } ' |
awk -F\" ' { print "url \= \"http\:\/\/room\.event\.assist\.com\/event\/room\/event\/'{ print $1 }'\?schema\=1\.3\.0\&form\=json\&pretty\=true\&token\=582EVTY78-03iBkTAf0JAhwOBx\&account\=room_event\"" } '
awk: non-terminated string url = "ht... at source line 1
context is
>>> <<<
awk: giving up
source line number 2
The line below exports out a single column of ID's:
grep "id\": \"http://room.event.assist.com/event/room/event/" failed_events.txt |
head -n1217 |
awk -F/ ' { print $7 } '
156512145
898545774
454658748
898432413
I'm looking to get the ID's above into a string like so:
" url = "string...'ID'string"
take a look what you have in last awk :
awk -F\"
' #single start here
{ print " #double starts for print, no ends
url \= \"http\:\/\/room\.event\.assist\.com\/event\/room\/event\/
' #single ends here???
{ print $1 }'..... #single again??? ...
(rest codes)
and you want to print exact {print } out? i don't think so. why you were nesting print ?
Most of the elements of your pipe can be expressed right inside awk.
I can't tell exactly what you want to do with the last awk script, but here are some points:
Your "grep" is really just looking for a string of text, not a
regexp.
You can save time and simplify things if you use awk's
index() function instead of a RE. Output formats are almost always
best handled using printf().
Since you haven't provided your input data, I can't test this code, so you'll need to adapt it if it doesn't work. But here goes:
awk -F/ '
BEGIN {
string="id\": \"http://room.event.assist.com/event/room/event/";
fmt="url = http://example.com/event/room/event/%s?schema=whatever\n";
}
count == 1217 { nextfile; }
index($0, string) {
split($7, a, "\"");
printf(fmt, a[0]);
count++;
}' failed_events.txt
If you like, you can use awk's -v option to pass in the string variable from a shell script calling this awk script. Or if this is a stand-alone awk script (using #! shebang), you could refer to command line options with ARGV.

multiple commands inside a awk

sry opening a new thread but awk is driving me nuts! >< im trying to run a few command assignments inside a single awk but i cant get it to work please help if this is ez for u :P i can't get the syntax to work
edit: im using /bin/bash
for f in `seq $nlinpE $loopE`;
do
awk -F ","'
BEGIN {}
'$f' { dataI2[$f]=$2;
dataI3[$f]=$3;
dataI4[$f]=$4;
noD1[$f]=$dataI1[$f];
noD2[$f]=$dataI2[$f];
noD3[$f]=$dataI3[$f];
noD1i[$f]=`echo "$nlinpN1 + $dataI1"|bc -l`;
noD2i[$f]=`echo "$nlinpN1 + $dataI2"|bc -l`;
noD3i[$f]=`echo "$nlinpN1 + $dataI3"|bc -l`;
}
'${noD1i[$f]}' {
dataIi2[$f]=$2;
dataIi3[$f]=$3;
dataIi4[$f]=$4;
}
'${noD2i[$f]}' {
dataIii2[$f]=$2;
dataIii3[$f]=$3;
dataIii4[$f]=$4;
}
'${noD2i[$f]}' {
dataIiii2[$f]=$2;
dataIiii3[$f]=$3;
dataIiii4[$f]=$4;
}
END{}
' <aoa_5.inp;
done
input is like:
17, 3.22854114, 0.562598288, 0.384291202
18, 2.96085286, 0.085116826, 0.285071939
19, 3.40070796, 2.27838659, 0.302027524
20, 3.20035744, 0.333615214, 0.262585849
21, 2.85644341, 0.258691043, 0.369726121
22, 3.73537922, 1.3267405, 0.295917094
23, 3.69372559, 1.32601321, 0.306054831
24, 3.28857207, 0.63199228, 0.378117412
25, 3.27523994, 0.695856452, 0.377585977
imjust assigning variables atm, getting the number w/o commas
i get this syntax type of error:
awk: 9: unexpected character '`'
awk: 10: unexpected character '`'
awk: 11: unexpected character '`'
(standard_in) 2: syntax error
(standard_in) 2: syntax error
awk: line 1: syntax error at or near {
^C
thx
Maybe this will help you clean up your syntax a little so we can understand what you're trying to do.
BEGIN and END blocks are optional. Ignoring patterns for the moment, an awk program might look like this.
BEGIN {
# Things to be done before you start processing rows.
}
{
# Things to be done for each row.
}
END {
# Things to be done after processing the last row.
}
If you don't happen to need BEGIN or END blocks, it might look more like this.
{
# Things to be done for each row.
}
This awk program assigns the value of $2, $3, and $4 to the variable dataI, and prints it once for each row.
{
dataI = sprintf("%s %s %s", $2, $3, $4);
print dataI;
}
That assignment has no effect on the values of $2, $3, and $4.