Trouble with passing Variable from bash to awk gsub command

Would really appreciate it if someone could point out my mistake in this line of code, i've been staring blankly at it trying everything i can think of some time now and coming up with nothing.

#!/bin/bash
echo "Enter Username"
read Username

awk -F: -v var=${Username} '/^var:/ {gsub(/foo/,"bar", $2); print}' FILENAME

Have already tried...

awk -F: -v var=${Username} "/^$var:/" '{gsub(/foo/,"bar", $2); print}' FILENAME

awk -F: -v var=${Username} "/^var:/" '{gsub(/foo/,"bar", $2); print}' FILENAME

awk -F: -v var="$Username" "/^var:/" '{gsub(/foo/,"bar", $2); print}' FILENAME

Desired output is to have the script replace "foo" with "bar" in field 2 of FILENAME only on lines beginning with Username entered into read.

After this step the idea is to replace "foo" with ANY data that's in the specified Field, and the Field number to also be specified by the user via a read command.
So if anyone knows a simpler command for doing that all in 1 go that'd be much appreciated too.

Hi,

After searching this forum for "How to pass a variable to awk" and reading this.

Try:

awk -F: -v var=${Username} '$0 ~ var {gsub(/foo/,"bar",$2); print}'  FILENAME

'var' is being treated as a literal string and not as a 'variable'

HTH

Thanks for the reply.

awk -F: -v var=${Username} '$0 ~ var {gsub(/foo/,"bar",$2); print}'  FILENAME

Changes every instance of foo in the second field into bar, not just on lines starting with the Username

This would better match the requirement:

awk -F: '/^'"$Username"':/ {gsub(/foo/,"bar", $2); print}' FILENAME

Here is what I tried.

less FILENAME

less test.sh

#!/bin/bash

echo "Enter Username"
read Username

awk -F: -v var=${Username} '$0 ~ var {gsub(/foo/,"bar",$2); print}'  FILENAME

bash test.sh

less FILENAME

I am using GNU Awk 3.1.7

This is what I tested with. Maybe you could give a sample of the result you are getting.

1 Like

Thanks for the help but that doesn't produce any output for me.

do you not have to -v and assign the shell variable as an awk variable before using it with an awk command?

---------- Post updated at 06:25 AM ---------- Previous update was at 06:21 AM ----------

I just created the exact same files you have used and it works perfectly, yet there's no difference i can see in my practical file...

two seconds and i'll run some more tests...

EDIT:

This will teach me for trying to write scripts after being awake for 24 hours.
My shell variable was named $UserName

the variable i was trying to use was name $Username

simple idiotic mistake.
Thanks for your help, your last post really made me go back and look at other things it could be once i knew the syntax was already correct.

---------- Post updated at 06:31 AM ---------- Previous update was at 06:25 AM ----------

One more thing before you dissappear.

read FieldNo

awk -F: -v var=${Username} -v var2=${FieldNo} '$0 ~ var {gsub($var2,"bar"); print}' FILENAME

is this possible to do with $var2 specifiying the field to replace. if the input at read FieldNo is a number, for example "2"

or even

 read data
read newdata

awk -F: -v var=${Username} -v var1=${data} -v var2=${newdata} '$0 ~ var {gsub(var1,var2); print}' FILENAME

gsub does a global substitution. So try sub?

#!/bin/bash

echo "Enter Username"
read Username
echo "Field"
read FieldNo

awk -F: -v var=${Username} -v var2=${FieldNo} '$0 ~ var {sub($var2,"bar"); print}' FILENAME

Output

bar

does it work your end?

once again it works in my TEST directory, but not the real thing. Checked all variables this time...

Using

#!/bin/bash

echo "Enter Username"
read Username
echo "Field"
read FieldNo

awk -F: -v var=${Username} -v var2=${FieldNo} '$0 ~ var {sub($var2,"bar"); print}' FILENAME
$bash test.sh
Enter Username
Carl
Field
3
Carl foo bar
$less FILENAME
Richard:foo:foo
Sam:foo:foo
Carl:foo:foo

Moving on to your other request. What you posted should also work. But it would replace *all* occurrances of data with newdata in that record. Using sub will replace the first occurance of that data with newdata in that record.

read data
read newdata

awk -F: -v var=${Username} -v var1=${data} -v var2=${newdata} '$0 ~ var {gsub(var1,var2); print}' FILENAME

Double check, my suggestion definitely works. This script:

#!/bin/bash

cat >FILENAME <<%
Quote:
Richard:foo
Sam:foo
Carl:foo
Bug:foo Richard
%

set -x
Username=Richard
awk -F: '/^'"$Username"':/ {gsub(/foo/,"bar", $2); print}' FILENAME

awk -F: -v var=${Username} '$0 ~ var {gsub(/foo/,"bar",$2); print}'  FILENAME

produces this output:

+ Username=Richard
+ awk -F: '/^Richard:/ {gsub(/foo/,"bar", $2); print}' FILENAME
Richard bar
+ awk -F: -v var=Richard '$0 ~ var {gsub(/foo/,"bar",$2); print}' FILENAME
Richard bar
Bug bar Richard

There is extra line which doesn't match the requirement with the second awk oneliner.

You have to indeed. My point is you might just don't need an awk variable in the first place, especially if you use it only once.