Using a variable in an awk Bourne shell script - shell

I'm trying to write a script that will read the country I type in and then display the people who are from that country. It works fine when I write the code with the country I want in, but when I try to use a variable nothing happens. I've been working on this for hours, so could someone please help me. This is what I have so far.
echo Please choose a country
echo
read country
awk -F: -v theCountry="$country" '
BEGIN {
recordCount = 0
printf "\t\tPlayers from that country\n\n"
print theCountry
}
/theCountry/{
print $1
recordCount++
}
END {
}' playerFile
Where I enter theCountry is where it's messing up.

Change:
/theCountry/{
to:
$0 ~ theCountry {
and read http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps

Related

Bash script does nothing when I run it, seems to keep waiting

I've written my first script, one in which I want to know if 2 files have the same values in a specific column.
Both files are WEKA machine-learning prediction outputs for different algorithms, hence they have to be in the same format, but the prediction column would be different.
Here's the code I've written based on the tutorial presented in https://linuxconfig.org/bash-scripting-tutorial-for-beginners:
#!/bin/bash
lineasdel1=$(wc -l $1 | awk '{print $1}')
lineasdel2=$(wc -l $2 | awk '{print $1}')
if [ "$lineasdel1" != "$lineasdel2" ]; then
echo "Files $1 and $2 have different number of lines, unable to perform"
exit 1
fi
function quitalineasraras {
awk '$1!="==="&&NF>0'
}
function acomodo {
awk '{gsub(/^ +| +$/, ""); gsub(/ +0/, " W 0"); gsub(/ +1$/, " W 1"); gsub(/ +/, "\t") gsub(/\+\tW/, "+"); print}'
}
function procesodel1 {
quitalineasraras "$1" | acomodo
}
function procesodel2 {
quitalineasraras "$2" | acomodo
}
el1procesado=$(procesodel1)
el2procesado=$(procesodel2)
function pegar {
paste <(echo "$el1procesado") <(echo "$el2procesado")
}
function contarintersec {
awk 'BEGIN {FS="\t"} $3==$8 {n++} END {print n}'
}
unido=$(pegar)
interseccion=$(contarintersec $unido)
echo "Estos 2 archivos tienen $interseccion coincidencias."
I ran all individual codes of all functions in the terminal and verified they work successfully (I'm using Linux Mint 19.2). Script's permissions also have been changed to make it executable. Paste command also is supposed to work with that variable syntax.
But when I run it via:
./script.sh file1 file2
if both files have the same number of lines, and I press enter, no output is obtained; instead, the terminal opens an empty line with cursor waiting for something. In order to write another command, I've got to press CTRL+C.
If both files have different number of lines the error message prints successfully, so I think the problem has something to do with the functions, with the fact that awk has different syntax for some chores, or with turning the output of functions into variables.
I know that I'm missing something, but can't come up with what could be.
Any help will be appreciated.
what could be.
function quitalineasraras {
awk '$1!="==="&&NF>0'
}
function procesodel1 {
quitalineasraras "$1" | acomodo
}
el1procesado=$(procesodel1)
The positional variables $1 are set for each function separately. The "$1" inside procesodel1 expands to empty. The quitalineasraras is passed one empty argument "".
The awk inside quitalineasraras is passed only the script without the filename, so it reads the input for standard input, ie. it waits for the input on standard input.
The awk inside quitalineasraras without any file arguments makes your script seem to wait.

Assign the value of awk-for loop variable to a bash variable

content within the tempfile
123 sam moore IT_Team
235 Rob Xavir Management
What i'm trying to do is get input from user and search it in the tempfile and output of search should give the column number
Code I have for that
#!/bin/bash
set -x;
read -p "Enter :" sword6;
awk 'BEGIN{IGNORECASE = 1 }
{
for(i=1;i<=NF;i++) {
if( $i ~ "'$sword6'$" )
print i;
}
} ' /root/scripts/pscripts/tempprint.txt;
This exactly the column number
Output
Enter : sam
2
What i need is the value of i variable should be assigned to bash variable so i can call as per the need in script.
Any help in this highly appreciated.
I searched to find any existing answer but not able to find any. If any let me know please.
first of all, you should pass your shell variable to awk in this way (e.g. sword6)
awk -v word="$sword6" '{.. if($i ~ word)...}`...
to assign shell variable by the output of other command:
shellVar=$(awk '......')
Then you can continue using $shellVar in your script.
regarding your awk codes:
if user input some special chars, your script may fail, e.g .*
if one column had matched userinput multiple times, you may have duplicated output.
if your file had multi-columns matching user input, you may want to handle it.
You just need to capture the output of awk. As an aside, I would pass sword6 as an awk variable, not inject it via string interpolation.
i=$(awk -v w="$sword6" '
BEGIN { IGNORECASE = 1 }
{ for (i=1;i<=NF;i++) {
if ($i ~ w"$") { print i; }
}
}' /root/scripts/pscipts/tempprint.txt)
Following script may help you on same too.
cat script.ksh
echo "Please enter the user name:"
read var
awk -v val="$var" '{for(i=1;i<=NF;i++){if(tolower($i)==tolower(val)){print i,$i}}}' Input_file
If tempprint.txt is big
awk -v w="$word6" '
BEGIN { IGNORECASE = 1 }
"$0 ~ \\<w\\>" {
for(i=1;i<=NF;i++)
if($i==w)print i
}' tempprint.txt

Awk Command analyze and explain

I have tried reading some tutorial about awk script, but still have doubt with below scripts:
get_value_from_ini()
{
section=$1
key_name=$2
echo `awk -F '=' '/\['"$section"'\]/{a=1}a==1&&$1~/'"$key_name"'/{gsub(/[[:blank:]]*/,"",$2); print $2}' $cfg_file`
}
db_user=`get_value_from_ini DB DBUSER`
db_passwd=`get_value_from_ini DB DBPASSWD`
And input config ini file like:
....
[DB]
DBUSER=dbuser
DBPASSWD=dbpasswd
...
As I unserstand, in awk command, the pattern is "[DB]", and field seperator is '=', but it worked correctly and can return correct result, Why ? Could you help me understand it ?
Thanks a lot!
Although poorly written code you simply read from left to right:
-F '=' -- As you have said, set FS to =
'/\'"$section"'\]/{a=1} -- If the line contains the information stored in variable section then set a=1
a==1 && $1~/'"$key_name"'/ -- If 'a' set and first field contains the information stored in variable key_name, execute all between {}
{gsub(/[[:blank:]]*/,"",$2); print $2}' -- If previous step returns true, remove all whitespace from second field and then print it out
$cfg_file -- file to be read
Here is an alternative to get rid of all the extra quotes which make it very confusing to read and become possibly error prone:
get_value_from_ini()
{
awk -F '=' -vsection="$1" -vkey_name="$2" '$0 ~ "["section"]"{a=1}a==1 && $1 ~ key_name{gsub(/[[:blank:]]*/,"",$2); print $2}' $cfg_file`
}

awk: "not enough arguments to satisfy format string" error in script

I created a script to grab the data from our Unix server, however I am getting the below error:
awk: cmd. line:8: (FILENAME=- FNR=2) fatal: not enough arguments to satisfy format string
`|%-17s|%-16s|%-15s|'
^ ran out for this one
Below is the complete script:
#!/bin/sh
export TERM=xterm
ipath=/usr/local/nextone/bin
date=$(date +"%Y%m%d%H%M")
ifile="$(date '+/var/EndpointUsage_%I-%M-%p_%d-%m-%Y.csv')"
"$ipath"/cli iedge list | awk '
BEGIN { print "|-----------------|------------------|------------------|";
printf "|%-18s|%-17s|%-16s|\r\n","Registration ID", "Port", "Ongoing Calls"
}
/Registration ID/ { id = $3; next }
/Port/ { port = $3 ; next }
/Ongoing Calls/ {print "|-------------------|-----------------|------------- -----|";
printf "|%-18s|%-17s|%-16s|\r\n",id,port,$3 }
END{
print "|------------------|------------------|------------------|";
}'>> "$ifile"
Can anyone please help me on this, how can I resolve this error?
AFTER CHANGES the columns are showing correctly, but the Port column does not have any data. It should have 0 or if other endpoint have 1 o 2 Port number.
|-----------------|------------------|------------------|
|Registration ID |Port |Ongoing Calls |
|-------------------|-----------------|------------------|
|-------------------|-----------------|------------------
|CC_XXXXXX_01_0 | |174 |
|-------------------|-----------------|------------------|
The offending printf is:
printf "|%-18s|%-17s|%-16s|\r\n",id,$3
^^^^ awk wants to see a third parameter here
You have three %s sequences in the format string, so awk expects ,<something else> after the $3. I think maybe it's a copy and paste error. Since you are only printing two column headers, try removing the %-16s| at the end and seeing if that gives you the output you expect.
Edit Without seeing your input file, I don't know for sure. Try this, though -
/Registration ID/ { id = $3; next }
/Port/ { port = $3 ; next }
/Ongoing Calls/ {print "|-------------------|-----------------|------------------|";
printf "|%-18s|%-17s|%-16s|\r\n",id,port,$3 }
I added {port=$3;next} to save the port number, and then when you print them out, I changed id,$3 to id,port,$3 to print the saved id, saved port, and ongoing-calls value ($3) in order.

How to send an E-mail with AWK using the SYSTEM command

So I have this uni homework where I need to send an E-mail to all the people from a certain group of students (which are listed in the diak.lst file) and to attach the text from a file to the mail as well. The address of the students is in a similar form: xy9999, 2 characters and 4 numbers.
The problem seems to be at the SYSTEM part, it says that there is no such thing as "attachedfile".
The diak.lst is in the following format:
F-Name,Name,Address,Group
George Peter gp9999 511
This is the script
#!/bin/bash
if [ ! -f $2 ]
then echo $2 Not a file!!
exit 1
fi
awk -v group=$1 -v attachedfile=$2 'BEGIN {fs=" ";nr_sent_to=0;}
{
if ($4==group){
system("mail -s \"Attention!\"" $3 " < " attachedfile);
nr_sent_to++;
}
}
END {
print nr_sent_to,"-have received the mail";
}
' diak.lst
You dont have a space before $3 in the string mail sees- try changing \"Attention!\"" $3 to \"Attention!\" " $3.
You have fs=" " which does nothing. Maybe you mean FS=" " but that's the default value so it will do nothing.
Your input file has a comma-separated header line so when processing that $3 etc. will be blank, add a NR>1 clause.
awk vars already init to 0/NULL so no need for nr_sent_to=0. You do have to then add +0 when printing it in the END section to make sure the number zero instead of the NULL string is printed if/when no emails are sent.
Given that everything you are doing in the BEGIN section is doing nothing useful, get rid of the BEGIN section.
Won't affect the script execution but: awk is not C - lose all the useless trailing semi-colons.
Put conditions in the condition part of the script, not the action part.
Quote your shell variables.
So with a bit more cleanup the end result would be:
awk -v group="$1" -v attachedfile="$2" '
NR>1 && ($4==group) {
system("mail -s \"Attention!\" " $3 " < " attachedfile)
nr_sent_to++
}
END {
print nr_sent_to+0, "-have received the mail"
}
' diak.lst

Resources