unable to run awk command as a shell script - unix

i am trying to create a shell script to search for a specific index in a multiline csv file.
the code i am trying is:
#!/bin/sh
echo "please enter the line no. to search: "
read line
echo "please enter the index to search at: "
read index
awk -F, 'NR=="$line"{print "$index"}' "$1"
the awk command I try to use on the shell works absolutely fine. But when I am trying to create a shell script out of this command, it fails and gives no output. It reads the line no. and index. and then no output at all.
is there something I am doing wrong?
I run the file at the shell by typing:
./fetchvalue.sh newfile.csv

Your quoting is not going to work. Try this:
awk -F, 'NR=="'$line'"{print $'$index'}' "$1"

Rather than going through quoting hell, try this:
awk -F, -v line=$line -v myindex=$index 'NR==line {print $myindex}' "$1"
(Index is a reserved word in awk, so I gave it a slightly differet name)

Related

Unix command to parse string

I'm trying to figure out a command to parse the following file content:
Operation=GET
Type=HOME
Counters=CacheHit=0,Exception=1,Validated=0
I need to extract Exception=1 into its own line. I'm fiddling with awk, sed and grep but not making much progress. Does anyone have any tips on using any unix command to perform this?
Thanks
Since your file is close to bash syntax, there is a fun little trick you can do to make bash itself parse the file. First, use some program like tr to transform the input into a something bash can parse, and then "source" that, which will create shell variables you can expand later to get the values.
source <(tr , $'\n' < file_name_goes_here)
echo $Exception
Many ways to do this. Here is one assuming the file is called "file.txt". Grab the line you want, replace everything from the start of the line up to Except with just Except, then pull out the first field using comma as the delimiter.
$ grep Exception file.txt | sed 's/.*Except/Except/g' | cut -d, -f 1
Exception=1
If you wanted to use gawk:
$ grep Exception file.txt | sed 's/.*Except/Except/g' | gawk -F, '{print $1}'
Exception=1
or just using grep and sed:
$ grep Exception file.txt | sed 's/.*\(Exception=[0-9]*\).*/\1/g'
Exception=1
or as #sheltter reminded me:
$ egrep -o "Exception=[0-9]+" file.txt
Exception=1
No need to use a mix of commands.
awk -F, 'NR==2 {print RS$1}' RS="Exception" file
Exception=1
Here we split the line by the keyword we look for RS="Exception"
If the line has two record (only when keyword is found), then
print first field, separated using command, with Record selector.
PS This only works if you have one Exception field

Handling file permissions in UNIX using awk

I want to know which permission is given to a file using a shell script. So i used the below code to test for a file. But it shows nothing in output. I just wanted to know where i have made the mistake. Please help me.
The file "1.py" has all read write and execute files enabled.
ls -l 1.py | awk ' {if($1 -eq "-rwxrwxrwx")print 'True'; }'
The single quotes (') around True should be double quotes ("), and awk uses == for string comparison.
However, depending on what you're trying to do, it might be cleaner to use the Bash builtin tests:
if [ -r 1.py -a -x 1.py ]; then
echo "Yes, we can read (-r) and (-a) execute (-x) the file"
else
echo "No, we can't."
fi
This avoids having to parse ls output. For a longer list of checks, see tldp.org.
in awk, you shouldn't write shell test, e.g. [[ ... -eq ...]], you should do it in awk way:
if($1=="whatever")...
you could use
ls -l 1.py | awk '{if ($1 == "-rwxrwxrwx") print "True" }'

I need to make a unix script to read first word from a file

I need to make a unix script to read first word from a file, and if that is "Mon,Tue....Sat,Sun" then it will print echo 0 or else echo 1
I was trying with grep command but it didn't worked
This could even be done without grep or awk, using just bash builtins (assuming your shell is bash - this should also work in ksh and also zsh, and maybe in sh, but not csh, where the syntax is quite a bit different):
read firstword otherstuff < myfile.txt
case "${firstword}" in
Sun|Mon|Tue|Wed|Thu|Fri|Sat) echo 1;;
*) echo 0;;
esac
You could also use regexp matching to avoid the case statement (this is definitely bash-only, though):
if [[ "${firstword}" =~ ^(Sun|Mon|Tue|Wed|Thu|Fri|Sat)$ ]]; then
That's just a matter of preference, though...
When you need to parse input for words awk is better then grep, it still can do what grep does, but also can precess every line with simple scripts.
This is my take on solution:
awk 'NR==1{c=0} $1~/Sun|Mon|Tue|Wed|Thu|Fri|Sat/{c=1} END{print c}' test.txt
I encourage you to learn more about awk in this (short) tutorial
Try egrep command like:
head -1 myfile.txt | egrep '^[Sun|Mon|Tue|Wed|Thu|Fri|Sat] .*'; echo $?

Variable pattern matching awk

I have an input file "myfile" and a shell variable "VAR" whose
contents are shown below:
# cat myfile
Hello World
Hello Universe
# echo $VAR
World
I need to process all lines in "myfile" which contains pattern "World"
using awk. It works if i do as shown below:
# awk '/World/ { print $0 }' myfile
But i could not use VAR to do the same operation. I tried the
following even knowing that these will not work:
# awk '/$VAR/ { print $0 }' myfile
and
# awk -v lvar=$VAR '/lvar/ { print $0 }' myfile
and
# awk -v lvar=$VAR 'lvar { print $0 }' myfile
Please let me know how to match the contents of VAR in awk.
Thanks in advance
You could use:
awk -v lvar="$VAR" '$0~lvar {print}' myfile
Or (works but not recommended):
awk "/$VAR/ {print}" myfile
This is probably what you want:
awk -v lvar="$VAR" '$0~lvar' myfile
Never do
awk "/$VAR/" myfile
or any other syntax that expands shell variables inline within the awk script such that they become part of the script as it can produce all sorts of bizarre failures and error messages depending on how the shell variable is populated since with that syntax there is no variable inside awk but the shell variable contents are instead integrated into the script as if you'd hard-coded it.
Always do the above using -v or
awk 'BEGIN{lvar=ARGV[1]; delete ARGV[1]} $0~lvar' "$VAR" myfile
depending on your requirements for the shell expanding backslashes. See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details.
Only do
awk '$0~lvar' lvar="$VAR" myfile
if you are processing multiple files, need to change initial values of the variable between files, and do not have gawk for BEGINFILE or need to populate those values from environment variables.
Note that all of the above do a regexp match on lvar, if you need a string match instead than use awk -v lvar="$VAR" 'index($0,lvar)'.
If you export your variable, it becomes a simpler solution:
export VAR
awk '$0~ENVIRON["VAR"]' myfile
Takes out any issues of reprocessing the variable's value.

awk getline not accepting external variable from a file

I have a file test.sh from which I am executing the following awk command.
awk -f x.awk < result/output.txt >>difference.txt
x.awk
while (getline < result/$bld/$DeviceType)
the variable DeviceType and bld are available in test.sh.
I have declared them as export type.
export DeviceType=$line
Even then while executing test.sh file, the script stops at following line
awk -f x.awk < result/output.txt >>difference.txt
and I am getting
awk: x.awk:4: (FILENAME=- FNR=116) fatal: division by zero attempted
error.
The awk script is read by awk, not touched by the shell. Inside an awk script, $bld means 'the field designated by the number in the variable bld' (that's the awk variable bld).
You can set awk variables on the command line (officially with the -v option):
awk -v bld="$bld" -v dev="$DeviceType" -f x.awk < result/output.txt >> difference.txt
Whether that does what you want is still debatable. Most likely you need x.awk to contain something like:
BEGIN { file = sprintf("result/%s/%s", bld, dev); }
{ while ((getline < file) > 0) print }
awk is not shell just like C is not shell. You should not expect to be able to access shell variables within an awk program any more than you can access shell variables within a C program.
To pass the VALUE of shell variables to an awk script, see http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details but essentially:
awk -v awkvar="$shellvar" '{ ... use awkvar ...}'
is usually the right approach.
Having said that, whatever you're trying to do it looks like the wrong approach. If you are considering using getline, make sure to read http://awk.freeshell.org/AllAboutGetline first and understand all of the caveats but if you tell us what it is you're trying to do with sample input and expected output we can almost certainly help you come up with a better approach that has nothing to do with getline.

Resources