Gawk error message fails on invocation line - awk

win7-64
cygcheck 3.1.7
gawk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1)
gawk outputs an error for the program invocation line. The program works in debug mode (gawk -D -f create) but not from inside my cygwin shell. Other gawk programs work fine. Please tell me what I am doing wrong?
> create 2000_RDA.csv
gawk: cmd. line:1: ./create
gawk: cmd. line:1: ^ syntax error
gawk: cmd. line:1: ./create
gawk: cmd. line:1: ^ unterminated regexp
The program
#! /bin/gawk
BEGIN {
outputLine[1] = " const string ";
outputLine[2] = " [] = { "
outputLine[4] = " , "
outputLine[5] = " }\n"
}
BEGINFILE {
line = 1;
name = "y" gensub(/_RDA.csv$/, "", "g", FILENAME);
printf("%s%s%s", outputLine[1], name, outputLine[2]);
}
ENDFILE {
printf("%s", outputLine[5]);
}
{
if (($0 ~ /^[[:digit:]]/)) { # begins with a number
if (line == 1) { printf("\"%s\"\n", $0); line = 0; }
else { printf("%s\"%s\"\n", outputLine[4], $0); }
}
}

Your shebang line is wrong. To use a file as an awk script, you have to add the -f option:
#!/bin/gawk -f
Shebang lines work by having the pathname of the script file and the arguments passed to the script appended to the line, so running create 2000_RDA.csv becomes /bin/gawk ./create 2000_RDA.csv, which means gawk treats ./create as the awk code to run. Adding the -f makes it /bin/gawk -f ./create 2000_RDA.csv, which will execute the code in the file (Which is now the argument of -f).

Related

AWK invalid char ''' in expression

The AWK command doesn't execute in a script but when checking in online awk validator shows my script has invalid char ''' in expression. Surprisingly I haven't changed anything in the awk command and was running all good till yesterday.
My Script:
awk '
BEGIN{ FS="," }
{
machinename=$1
compornot=$3
for (i=1; i<=NF; i++) {
if ($1 == machinename) {
if (compornot == "compliant" && $3 == "compliant") {
value = "NA"
} else if (compornot == "noncompliant" && $3 == "noncompliant") {
value = "No"
} else {
value = "Yes"
}
}
}
print $1 "," $2 "," compornot "," value "," $3
}
' $SCRIPT_PATH/$SCRIPT_NAME/kraft_ansible_temp.csv | tee $SCRIPT_PATH/$SCRIPT_NAME/kraft_ansible_temp.csv
Error in online AWK validator:
gawk: prog.awk:1: awk '
gawk: prog.awk:1: ^ invalid char ''' in expression
gawk: prog.awk:1: awk '
gawk: prog.awk:1: ^ syntax error`
The "script" you posted is a shell script, not an awk script. It does not conform to awk's syntax but rather a shell's, hence the syntax error.
The code between the two single quotes, on the other hand, is properly awk, so you should have the awk syntax validator validate that instead.

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" }
'

Redirecting output of command to file in awk

I need to redirect output of only a particular command within awk to a file.
I need to access the array outside the if.
What I've tried:
awk '
{
if (condition)
{
array[FNR]=$1;
print array[FNR];
df home/user/loc1 home/user/loc2 > file1.txt
}
fi
print array[]
}' /home/user/testfile.txt
Errors I'm getting:
awk: cmd. line:18: df home/user/loc1 home/user/loc2 > file1.txt
awk: cmd. line:18:
^ syntax error
awk: cmd. line:20: print array[]
awk: cmd. line:20: ^ syntax error
awk: cmd. line:20: fatal: invalid subscript expression
I believe this is what you are looking for,
awk '
{
if (condition)
{
array[FNR]=$1;
print array[FNR] # >> file2.txt (use this if you want to print to a file)
system("df home/user/loc1 home/user/loc2") >> file1.txt # Not sure why you want to run df shell command inside awk
}
} END { # after the entire test file is read you can do your calculations below
for (i in array) print array[i];
}' /home/user/testfile.txt

How to translate a column value in the file using awk with tr command in unix

Details:
Input file : file.txt
P123456789,COLUMN2
P123456790,COLUMN2
P123456791,COLUMN2
Expected output:
Z678999999,COLUMN2
Z678999995,COLUMN2
Z678999996,COLUMN2
If i try using a variable it is giving proper result.
(i.e) /tmp>echo "P123456789"|tr "0-9" "5-9"|tr "A-Z" "X-Z"
Z678999999
But if i do with awk command it is not giving result instead giving error:
/tmp>$ awk 'BEGIN { FS=OFS="," } { $1=echo $1|tr "0-9" "5-9"|tr "A-Z" "X-Z";$2="COLUMN2"); print }' /tmp/file.txt >/tmp/file.txt.tmp
awk: BEGIN { FS=OFS="," } { $1=echo $1|tr "0-9" "5-9"|tr "A-Z" "X-Z";$2="COLUMN2"); print }
awk: ^ syntax error
awk: BEGIN { FS=OFS="," } { $1=echo $1|tr "0-9" "5-9"|tr "A-Z" "X-Z";$2="COLUMN2"); print }
awk: ^ syntax error
awk: BEGIN { FS=OFS="," } { $1=echo $1|tr "0-9" "5-9"|tr "A-Z" "X-Z";$2="COLUMN2"); print }
awk: ^ syntax error
Can anyone help please?
just do what you wanted, without changing your logic:
awk line:
awk -F, -v OFS="," '{ "echo \""$1"\"|tr \"0-9\" \"5-9\"|tr \"A-Z\" \"X-Z\"" |getline $1}7'
with your data:
kent$ echo "P123456789,COLUMN2
P123456790,COLUMN2
P123456791,COLUMN2"|awk -F, -v OFS="," '{ "echo \""$1"\"|tr \"0-9\" \"5-9\"|tr \"A-Z\" \"X-Z\"" |getline $1}7'
Z678999999,COLUMN2
Z678999995,COLUMN2
Z678999996,COLUMN2
$ cat tst.awk
function tr(old,new,str, oldA,newA,strA,i,j) {
split(old,oldA,"")
split(new,newA,"")
split(str,strA,"")
str = ""
for (i=1;i in strA;i++) {
for (j=1;(j in oldA) && !sub(oldA[j],newA[j],strA[i]);j++)
;
str = str strA[i]
}
return str
}
BEGIN { FS=OFS="," }
{ print tr("P012345678","Z567899999",$1), $2 }
$ awk -f tst.awk file
Z678999999,COLUMN2
Z678999995,COLUMN2
Z678999996,COLUMN2
Unfortunately, AWK does not have a built in translation function. You could write one like Ed Morton has done, but I would reach for (and highly recommend) a more powerful tool. Perl, for example, can process fields using the autosplit (-a) command switch:
-a turns on autosplit mode when used with a -n or -p. An implicit split command to the #F array is done as the first thing inside the
implicit while loop produced by the -n or -p.
You can type perldoc perlrun for more details.
Here's my solution:
perl -F, -lane '$F[0] =~ tr/0-9/5-9/; $F[0] =~ tr/A-Z/X-Z/; print join (",", #F)' file.txt
Results:
Z678999999,COLUMN2
Z678999995,COLUMN2
Z678999996,COLUMN2

How to match new lines in awk?

Input file text.txt:
foo()
{
}
buz()
{
}
Awk script.awk:
BEGIN {
RS = "\n\n+";
FS = "\n";
}
/[a-z]+\(\)\n/ {print "FUNCTION: " $1;}
{print "NOT FOUND: " $0;}
Running script:
awk -f script.awk text.txt
gives:
NOT FOUND: foo()
{
}
NOT FOUND: buz()
{
}
But I've expected to match both functions WITH newlines. How to do this?
Since you're already using "\n" as the FS, you can just do matching against $1:
awk -v RS='\n\n+' -v FS='\n' '
$1 ~ /^[a-z]+\(\)$/ {print "FUNCTION: " $1; next}
{print "NOT FOUND: " $0}
' text.txt
This worked with gawk:
FUNCTION: foo()
FUNCTION: buz()
You can try this:
BEGIN {
RS = "";
FS = "\n";
}
/[a-z]+\(\)/ {print "FUNCTION: " $1;}
!/[a-z]+\(\)/ {print "NOT FOUND: " $0;}
If you want to verify that there is nothing after the () you can do this:
$1~/[a-z]+()$/ {print "FUNCTION: " $1;}
I don't know why newline isn't matched. Maybe someone would explain it.
This might work for you (GNU awk):
awk '{if(/^[a-z]+\(\)\n/)print "FUNCTION:"$1; else print "NOT FOUND: "$0}' RS="" file
Not sure what output you expect excactly.
In order to process FS in awk you need to indroduce a dummy command like $1=$1. Without it no filed parsing is done.
So if you expect result like this:
foo() { }
buz() { }
Just type:
awk '{$1=$1; print} ' RS='\n\n' FS='\n' OFS=" "