Passing bash input variables to awk - bash

Trying to pass a variable into awk from user input:
Have tried variations of awk -v with errors stating 'awk: invalid -v option', even though the option is listed in man files.
#! /bin/bash
read -p "Enter ClassID:" CLASS
read -p "Enter FacultyName:" FACULTY
awk '/FacultyName/ {print}' data-new.csv > $FACULTY.csv
awk -vclass=${CLASS} '/class/ {print}' data-new.csv >> $FACULTY.csv
echo Class is $CLASS
echo Faculty member is $FACULTY

Some versions of awk require a space between the -v and the variable assignment. Also, you should put the bash variable in double-quotes to prevent unwanted parsing by the shell (e.g. word splitting, wildcard expansion) before it's passed to awk. Finally, in awk /.../ is a constant regular expression (i.e. /class/ will search for the string "class", not the value of the variable "class"). With all of this corrected, here's the awk command that I think will do what you want:
awk -v class="${CLASS}" '$0 ~ class {print}' data-new.csv >> $FACULTY.csv
Now, is there any reason you're using this instead of:
grep "$CLASS" data-new.csv >> $FACULTY.csv

Your script is not clear to me, but these all work:
CLASS=ec123
echo | awk -vclass=$CLASS '{print class}'
echo | awk -vclass=${CLASS} '{print class}'

Related

Running awk command and print $1 with script that get arguments

I have my script (called test.sh) as follow:
#!/bin/bash
for i in "cat myfile | awk -F',' '{print $1}'"; do
.....
My problem is that my script receives arguments (./tesh.sh arg1 arg2) and '{print $1}' take the script argument (arg1) instead awk result, how can I solve it?
Your original problem is that you wrote the $1 between double-quotes.
"cat myfile | awk -F',' '{print $1}'"
bash variables are still substituted by their value if they are in a double-quoted string, disregarding the fact that they are between single-quotes inside the double-quotes. This is the reason why $1 is being replaced by arg1.
The second problem is that you want to execute the command:
cat myfile | awk -F',' '{print $1}'
but for this you need to use the notation $( command ) or `command`, the latter is however not advised as nesting is difficult.
So, your for-loop should read something like:
#!/usr/bin/env bash
for i in $(awk -F ',' '{print $1}' myfile); do
...
done

Awk output to shell variable with shell variable as search pattern

I'm trying to find (with awk) the IP of a specific ethernet interface using the hostname as a search patter (suffixed by the name of the ethernet interface). I wrote this little script but it outputs nothing and I don't understand why...
#!/bin/bash
name=$(hostname -s)-eth3
IP1=`awk -v var=$name '/var/ {print $1}' /etc/hosts`
echo $IP1
Could you please make few changes as shown following, which may help you.
#!/bin/bash
name=$(hostname -s)-eth3
IP1=$(awk -v var=$name '$0 ~ var{print $1}' "/etc/hosts")
echo "$IP1"
changes like backtick is not encouraged for storing values in bash variables $ should be used and use echo "$var" too.
Inside slashes, awk treats var as a literal string, not a variable.
Thus, replace:
/var/
With:
$0 ~ var
Thus use:
#!/bin/bash
name=$(hostname -s)-eth3
ip1=`awk -v var=$name '$0 ~ var {print $1}' /etc/hosts`
echo "$ip1"
Example
The first awk script below produces no match but the second does:
$ echo host-eth1 | awk -v var='host-eth1' '/var/ {print $1}'
$ echo host-eth1 | awk -v var='host-eth1' '$0 ~ var {print $1}'
host-eth1

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

Using variables with grep is not working

I have a file VALIDATION_CONFIG_FILE.cfg which contains the records below:
ES_VDF_1|1
DE_VDF_1|2
ES_VDF_1|7
When I am using the grep command below by using variable then the command is returning ES_VDF_1 output. As per my understanding, command should not give any results. When I use the same command without using variables (use values directly) then command is returning no results, which is as expected. So what is the problem with variables which I am using?
FEED_ID_1_7="HU_VDF_1"
FEED_ID_2_7="ES_VDF_1"
FEED_ID_3_7="PT_VDF_2"
awk -F'|' '{ if($2=="7") print $1; }' VALIDATION_CONFIG_FILE.cfg |
grep -E -v '${FEED_ID_1_7}|${FEED_ID_2_7}|${FEED_ID_3_7}'
Output: ES_VDF_1
awk -F'|' '{ if($2=="7") print $1; }' VALIDATION_CONFIG_FILE.cfg |
grep -E -v 'ES_VDF_1|HU_VDF_1|PT_VDF_2'
Output: nothing
The problem you are seeing is that single quotes in Bash do not interpolate variables, whereas double quotes do.
For example with a variable imaginatively called "VARIABLE":
alex#yuzu:~$ export VARIABLE="foo"
If you echo it with double quotes, it is interpolated and the value of the variable is used:
alex#yuzu:~$ echo "$VARIABLE"
foo
But if you use single quotes the literal string '$VARIABLE' is used instead:
alex#yuzu:~$ echo '$VARIABLE'
$VARIABLE
The same goes for your grep.
grep -E -v '${FEED_ID_1_7}|${FEED_ID_2_7}|${FEED_ID_3_7}'
Should be:
grep -E -v "${FEED_ID_1_7}\|${FEED_ID_2_7}\|${FEED_ID_3_7}"
For example:
alex#yuzu:~$ echo "foo" | grep -E "$VARIABLE|$HOME|$USER"
foo
alex#yuzu:~$ echo "foo" | grep -E '$VARIABLE|$HOME|$USER'
[ no output ]
This is happening due to quotes.
Single quotes won't interpolate anything, but double quotes will do. Replace single quotes to double quotes with variables like below :
awk -F'|' '{ if($2=="7") print $1; }' VALIDATION_CONFIG_FILE.cfg |
grep -E -v "${FEED_ID_1_7}|${FEED_ID_2_7}|${FEED_ID_3_7}"
Refer bash manual for more details
Adding to Kaoru/Nishu Tayal's answer, you can make it safer further by using normal text search with fgrep and multiple -e:
fgrep -v -e "${FEED_ID_1_7}" -e "${FEED_ID_2_7}" -e "${FEED_ID_3_7}"
This would help prevent misinterpretations just in case special characters would be added to the values of variables.
If you don't have fgrep try grep -F.

Shell - Awk - reading from variable

Is it possible to read for the awk input from variable (e.g. i) instead of file ?
awk 'something' temp
Can the 'temp' be replaced by the variable $i ? Really couldn't find it in man pages.
If your variable is a string, you can do that by using Bash here-string notation.
awk 'something' <<< "$temp"
For example:
$ temp='hello:world'
$ awk -F':' '{print $2}' <<< "$temp"
world
If you variable is a file, then just do
$ cat file
hello:world
$ f='./file'
$ awk -F':' '{print $1}' "$f"
hello
In a POSIX shell without here-string support, you can use a here-doc instead:
awk 'something' <<EOF
$i
EOF
awk 'something' <<< "$i" is just a shortcut for the above when the here document is very short or already contained in a variable.

Resources