Bash: AWK - $1 as first parameter of shell script - bash

I spent on this 2 hours and get nothing. I want to get $1 and $2 as a first command line input of shell script, but I couldn't manage this. And $3 and $0 would be columns in awk. I try different methods but nothing works for me.
awk -F':' -v "limit=1000" '{ if ( $3 >=limit ) gsub("~/$1/",~/$2/); print \$0}' file.txt

the cleanest method is to explicitly pass the values from shell to awk with awk's -v option:
awk -F: -v limit=1000 -v patt="~/$1/" -v repl="~/$2/" '
$3 >=limit {gsub(patt,repl); print}
' file.txt

When your awk line is part of a script file, and you want to use $1 and $2 from the script in your awk command, you should temporary stop the literal string with a single quote and start it again.
awk -F':' -v "limit=1000" '{ if ( $3 >=limit ) gsub("~/'$1'/",~/'$2'/); print $0}' file.txt

You didn't post any sample input or expected output so this is a guess but you probably want something like this:
awk -F':' -v limit=1000 -v arg1="$1" -v arg2="$2" '$3 >= limit{gsub("~/" arg1 "/","~/" arg2 "/"); print}' file.txt

Related

awk issue inside for loop

I have many files with different names that end with txt.
rtfgtq56.txt
fgutr567.txt
..
So I am running this command
for i in *txt
do
awk -F "\t" '{print $2}' $i | grep "K" | awk '{print}' ORS=';' | awk -F "\t" '{OFS="\t"; print $i, $1}' > ${i%.txt*}.k
done
My problem is that I want to add the name of every file in the first column, so I run this part:
awk -F "\t" '{OFS="\t"; print $i, $1}' > ${i%.txt*}
$i means the file that are in the for loop,
but it did not work because awk can't read the $i in the for loop.
Do you know how I can solve it?
You want to refactor eveything into a single Awk script anyway, and take care to quote your shell variables.
for i in *.txt
do
awk -F "\t" '/K/{a = a ";" $2}
END { print FILENAME, substr(a, 1) }' "$i" > "${i%.txt*}.k"
done
... assuming I untangled your logic correctly. The FILENAME Awk variable contains the current input file name.
More generally, if you genuinely want to pass a variable from a shell script to Awk, you can use
awk -v awkvar="$shellvar" ' .... # your awk script here
# Use awkwar to refer to the Awk variable'
Perhaps see also useless use of grep.
Using the -v option of awk, you can create an awk Variable based on a shell variable.
awk -v i="$i" ....
Another possibility would be to make i an environment variable, which means that awk can access it via the predefined ENVIRON array, i.e. as ENVIRON["i"].

Awk multiple search terms with a variable and negation

I have a little test file containing:
awk this
and not awk this
but awk this
so do awk this
And I've tried the following awk commands, in bash, but each produces no output:
f=awk; awk '/$f/ && !/not/' test.txt
f=awk; awk '/\$f/ && !/not/' test.txt
f=awk; awk '/"$f"/ && !/not/' test.txt
f=awk; awk -v f="$f" '/f/ && !/not/' gtest.txt
Using double quotes " produces "event not found" error in the shell due to the !.
How can I search on a variable and negate another string in the same command?
Use awk like this:
f='awk'
awk -v f="$f" -v n='not' '$0 ~ f && $0 !~ n' file
awk this
but awk this
so do awk this
Or if you don't want to pass n='not' to awk:
awk -v f="$f" '$0 ~ f && $0 !~ /not/' file
awk this
but awk this
so do awk this
awk points to gawk for me and the following worked just fine:
awk -vf=awk '$0 ~ f && !/not/' file

AWK: Passing two arguments and weird error

I have made an awk implementation of grep -c ^str file and I want to pass the file and str arguments from a shell script. I am using awk -v twice to pass the arguments but I get a awk: cannot open var1 (No such file or directory) error.
I just can't get around it, I've been trying for almost an hour.
My code:
read -p "Give me a file name " file
read -p "Give me a string " str
awk -v var1="$file" -v var2="$str" 'BEGIN{print var1; print var2}{/^var2/}' var1 |
awk '{if ($0 != "/s") {count++}} END {print count}'
It should be:
awk -v var1="$file" -v var2="$str" 'BEGIN{print var1; print var2}{/^var2/}' $file
awk vars can only be acceded inside awk code (delimited by single quotes in this case) not at shell level where var1 means nothing.
Note that var2 value will be just a literal string between slashes /^var2/, use $0 ~ "^"var instead to access var2 value.
In fact, your awk code can be rewritten as:
awk -v var="$str" '$0 ~ "^"var && $0 != "/s"{count++}END{print count}' $file

How to insert Command Line argument of shell script in AWK?

I have to find all of the record which have a particular data which I am gonna pass as the command line argument.
awk expression is like this(Date is in this format :'02/08/2013')
cat records.txt| awk -F ',' '$4 ~ /02/08/2013/ {print $1 $2}'
Here 4th column is the date column.
What I want to do is that, provide the date as the first argument and compare it.
I tried this,But it is not working.
cat records.txt| awk -F ',' -v awkvar="$1" '$4 ~ /^"awkvar/ {print $1 $2}'
Here the date column starts with " quote, so I am telling to look for the records who start with "+awkvar the given date.
Can anyone help me with this?
Edit:
awk -F ',' -v var1="$1" '$4 ~ /^"2013/ {print $1 $2}' {This one is working, as I am directly comparing the record with 2013}
when I do this
awk -F ',' -v var1="$1" '$4 ~ /^"var1/ {print $1 $2}' , it does not return anything, what is the difference.
To pass variables to awk, use
awk -v awkvar=$value '{print awkvar}'
That said, no need to pipe cat | awk (useless use of cat) so finally :
awk -F, -v awkvar="$1" '$4 ~ "^\""awkvar {print $1 $2}' records.txt

How to replace the nth column/field in a comma-separated string using sed/awk?

assume I have a string
"1,2,3,4"
Now I want to replace, e.g. the 3rd field of the string by some different value.
"1,2,NEW,4"
I managed to do this with the following command:
echo "1,2,3,4" | awk -F, -v OFS=, '{$3="NEW"; print }'
Now the index for the column to be replaced should be passed as a variable. So in this case
index=3
How can I pass this to awk? Because this won't work:
echo "1,2,3,4" | awk -F, -v OFS=, '{$index="NEW"; print }'
echo "1,2,3,4" | awk -F, -v OFS=, '{$($index)="NEW"; print }'
echo "1,2,3,4" | awk -F, -v OFS=, '{\$$index="NEW"; print }'
Thanks for your help!
This might work for you:
index=3
echo "1,2,3,4" | awk -F, -v OFS=, -v INDEX=$index '{$INDEX="NEW"; print }'
or:
index=3
echo "1,2,3,4" | sed 's/[^,]*/NEW/'$index
Have the shell interpolate the index in the awk program:
echo "1,2,3,4" | awk -F, -v OFS=, '{$'$index'="NEW"; print }'
Note how the originally single quoted awk program is split in three parts, a single quoted beginning '{$', the interpolated index value, followed by the single quoted remainder of the program.
Here's a seductive way to break the awkwardness:
$ echo "1,2,3,4" | sed 's/,/\n/g' | sed -e $index's/.*/NEW/'
This is easily extendable to multiple indexes just by adding another -e $newindex's/.*/NEWNEW/'
# This should be faster than awk or sed.
str="1,2,3,4"
IFS=','
read -a f <<< "$str"
f[2]='NEW'
printf "${f[*]}"
With plain awk (I.E. Not gawk etc) I believe you'll have to use split( string, array, [fieldsep] ); change the array entry of choice and then join them back together with sprintf or similar in a loop.
gawk allows you to have a variable as a field name, $index in your example. See here.
gawk is usually the default awk on Linux, so change your invocation to gawk "script" and see if it works.

Resources