Variables in an awk command

I am scripting a process where usernames are added to the end of a specific line in a file.

using this:

awk 'NR==1{$NF=$NF" TEXT"}1' myfile

works, and then I would use

> tempfile && mv tempfile myfile

HOWEVER. Being that this is to be scripted, I am trying to do something like:

awk: NR=="${chosenline}"{$NF=$NF" ${enteredtext}"}1

when I run through the script like this, my variables are populated, and in the awk command, however the NF's are gone. How can I get the NF value to work as it does without variables, but work when there are variables?

Any and all help would be greatly appreciated

Define awk variables and use them in your program:

awk -v L="$chosenline" -v T="$enteredtext" 'NR==L{$NF=$NF T}1' myfile

The issue is not the variables. $NF is not there. I am debugging by using echo to see the generated command. It comes out like this:

awk 'NR==1{ = TEXT}1' myfile

It seems $NF in your awk program got disappeared due to shell variable expansion before you program executed.

You might have to escape the dollar sign \$ to avoid that. Or post your code so that we can help.

1 Like

Thank you Yoda, you truly are a Jedi Master! the escapes seem to help some, but I am still "so close, yet so far away". I am posting my code here, I have documented where the issue is, and it is set up for debugging as it is. I can echo the command and the results are what I want, but it still is not quite perfect.

#!/bin/bash
#
#
#
#
#
#Adds username to .group file with prompts
#
########################################

# Lets the user know that they will have a backup of the .group file

clear

echo "==================================================="
echo "Welcome to the Report Access Tool.  As a precaution"
echo "a copy of the customer .group file will be copied  "
echo "to your home directory before the command completes"
echo "PRESS ENTER TO CONTINUE .......................  "
echo "==================================================="

read


clear

# prompt for username

echo "================================================="
echo "Enter the username that needs to access reports?"
echo "================================================="

read EmonUser

clear

# get customer

echo "================================================="
echo "  Which customer's reports are they accessing?"
echo "================================================="

read customer




# here is where we are sending a backup of the file, before doing our work, just in case
# commented out for testing
cp $customer.group ~/$customer.group.bak


# initiate a loop sequence that will allow the user to be added to multiple groups

while [ "$loop" != "n" ]
do

clear

echo "================================================="
echo "  Which report does this user need access to?"
echo "================================================="

# this line uses awk to display the group names of all lines in the file
awk -F':' '{ print NR " " $1 }' $customer.group


read reportline




# THIS IS THE COMMAND THAT HAS THE ISSUE. SET AS VARIABLE ONLY FOR DEBUGGING
keycommand="awk 'NR=="${reportline}"{\$NF=\$NF\" "${EmonUser}"\"}1' $customer.group"

echo $keycommand


# uncomment this read line to debug the above  command with echo
read
# ABOVE THIS LINE IS ONLY USED AT THIS TIME FOR DEBUGGING the results of echo $keycommand at this point are what needs to run
# once that piece works, I will append the > AddToGroup.tmp && mv AddToGroup.tmp $customer.group


clear

echo "====================================================="
echo "Do you want to add this user to another report? (Y/N)"
echo "====================================================="

read doitagain

# nested loop will repeat first loop until they answer no to adding to another group.


while [ "doitagain" != "n" ]
do

# case statment will exit this loop if they want to add to another report
# or will exit this loop, and then close the first loop, ending the script for no
# if the input is not Y or N, second loop starts again, forcing a valid answer
case $doitagain
in
[nN]) doitagain="n" ; loop="n" ; clear; break;;
[yY]) doitagain="y" ; break;;
   *) clear; echo "====================================================="; echo "Invalid action.  Add to another report?  Y or N"; echo "====================================================="; read doitagain;;
esac

done

# cleans up the temp file created
#rm AddToGroup.tmp

done

Why do you store the shell command in a variable first?
It makes things complicated.
Directly run it, and becomes

awk 'NR=='$reportline' {$NF=$NF" '$EmonUser'"} 1' $customer.group

or the better readable

awk 'NR==L {$NF=$NF" "U} 1' L=$reportline U=$EmonUser $customer.group

storing in the variable makes the echo command, which is used to debug. currently, the command does not work. for some reason, it does not keep all variables, and the NF, even when using escapes. if you copy the script, and create a TEST.group file, and try to run it you will see. If I run the command from the shell directly, it works. when I run the same awk command in the script, it does not function properly. storing it to a variable, and then echo that, allows me to see what is actually being run. however, what comes in the echo is correct, and manipulates the file how I want it to. yet when I run the script without the debugging, it does not manipulate the file as desired.

Prefix the direct command with echo command for debugging

echo awk 'NR==L {$NF=$NF" "U} 1' L=$reportline U=$EmonUser $customer.group

For debugging while really running, use

set -vx # debug on
awk 'NR==L {$NF=$NF" "U} 1' L=$reportline U=$EmonUser $customer.group
set +vx # debug off
1 Like

Thank you MadeInGermany! Your modification to the direct command works perfectly!

SOLVED!