Use Awk script from shell to search into a text file - unix

so there is my problem, it is a very trivial one I assume but I can't for the life of me find a solution.
I want to learn to use awk to manipulate text files. I know python and can use it to this effect but I've been told by my supervisor that i was to use Awk.
I am experimenting on cygwin at home but in the end I will work with UNIX
My probelm is with basic Awk syntax. I want to write my awk script in a text file and call it from the command line in the following way.
./scirptname filename
when I'm using a very simple Helloworld script there is no problem.
Now I want to try and search for a line containing the a keyword.
My script looks like this
#! /bin/awk
BEGIN {
}
{
'/keyword/ {print}'
}
when I attempt to run it on a file know contains this keyword I get the following error message
gawk: cmd. line:1: ./test1
gawk: cmd. line:1: ^ syntax error
gawk: cmd. line:1: ./test1
gawk: cmd. line:1: ^ unterminated regexp
So once again, sorry to bother you with this very simple and trivial question, but how do I feed a file name to my script and have my script perform the task I want it to perform on that file.
I don't want to make a one liner from shell, what I would like to do on those files is a bit too complex for that (in my ignorant uneducated opinion).
I would really really apreciate the help.

Problem one:
You didn't understand awk's pattern and actions well. google some tutorial and read that part.
like : http://www.chemie.fu-berlin.de/chemnet/use/info/gawk/gawk_9.html
in your awk file, you should either have:
#! /bin/awk -f
BEGIN {} {if(/keyword/) {print}}
or
#! /bin/awk -f
BEGIN {} /keyword/ {print}
in fact, the above line could be shorten into (assume you need the BEGIN block):
#!/bin/awk -f
BEGIN {} /keyword/
Problem two:
the hashbang line need -f so :
#!/bin/awk -f
then you could under same dir, do:
./myawk.awk inputfile

Related

Unix awk what does f=1 do

So right now I am read some unix script and I am not quite sure if it does what I think it does.
foo=/some/directory/rules
awk '/^test=/ { print "test="foo; f=1 }
f==0 { print }
{ f=0 }' \
/some/other/directory/file
My guess is that this should not run ( because of "test="foo ), but it does - so I think the intend is that if a line out of '/some/other/directory/file' matches it gets written to '/some/directory/rules' with the praefix "test=", other wise it just gets printed on the console?
I am unable to find something in the man pages and the examples also don't use the f=? syntax
Get the book Effective Awk Programming, Third Edition by Arnold Robbins as you currently are very confused about awk syntax. The intent of the script you posted is to print the contents of /some/other/directory/file to stdout, except when a line starts with test= and in that case replace that line with one that says test=/some/directory/rules.
The more awk-ish way to write that would simply be:
foo=/some/directory/rules
awk -v foo="$foo" '{print (/^test=/ ? "test="foo : $0)}' /some/other/directory/file

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.

unix script using sed

Im trying to get the following script to work, but Im having some issues:
g++ -g -c $1
DWARF=echo $1 | sed -e `s/(^.+)\.cpp$/\1/`
and Im getting -
./dcompile: line 3: test3.cpp: command not found
./dcompile: command substitution: line 3: syntax error near unexpected token `^.+'
./dcompile: command substitution: line 3: `s/(^.+)\.cpp$/\1/'
sed: option requires an argument -- 'e'
and then bunch of stuff on sed usage. What I want to do is pass in a cpp file and then extract the file name without the .cpp and put it into the variable DWARF. I would also like to later use the variable DWARF to do the following -
readelf --debug-dump=info $DWARF+".o" > $DWARF+".txt"
But Im not sure how to actually do on the fly string concats, so please help with both those issues.
You actually need to execute the command:
DWARF=$(echo $1 | sed -e 's/(^.+)\.cpp$/\1/')
The error message is a shell error because your original statement
DWARF=echo $1 | sed -e `s/(^.+)\.cpp$/\1/`
is actually parsed like this
run s/(^.+)\.cpp$/\1/
set DWARF=echo
run the command $1 | ...
So when it says test3.cpp: command not found I assume that you are running with argument test3.cpp and it's literally trying to execute that file
You also need to wrap the sed script in single quotes, not backticks
In BASH you can crop off the extension from $1 by
${1%*.cpp}
if you need to set the DWARF var use
DWARF="${1%*.cpp}"
or just reference $1 as
readelf --debug-dump=info "${1%*.cpp}.o" > "${1%*.cpp}.txt"
which will chop off the rightmost .cpp so test.cpp.cpp will be test.cpp
You can use awk for this:
$ var="testing.cpp"
$ DWARF=$(awk -F. '{print $1}' <<< $var)
$ echo "$DWARF"
testing

Accepting command line parameters in awk

I've looked around for awhile and found only either questions touching on the subject or providing me with an answer that does not work. Here's the question:
I'm working on an assignment for school that requires me to read in command line arguments for an awk script (which seems odd to begin with, but eh). We're using an older version of Unix and I'm running Bash. This awk only has the -f and -Fc options. Basically, I keep trying to do "awk -f awk_script arg1 arg2 arg3 arg4 arg5 arg6" but each time awk attempts to open arg1 as a file, which it isn't. An example I saw elsewhere addressing this was:
awk 'BEGIN { print "ARGV[1] = ", ARGV[1] }' foo bar
It was supposed to print "foo", but on this system I only get the output "ARGV[1] = awk: can't open foo". So, in summary, is there any way around this? Can an awk this old read command line arguments and use them for anything other than input files? The instructors notes file hinted at the above usage (of printing foo), but his program doesn't even run, so...
Any help would be greatly appreciated.
After Edit: Using SunOS 5.10 and this awk does not support the -v option, ONLY the -f and -Fc
You can decrement ARGC after reading arguments so that only the first(s) argument(s) is(are) considered by awk as input file(s) :
#!/bin/awk -f
BEGIN {
for (i=ARGC; i>2; i--) {
print ARGV[ARGC-1];
ARGC--;
}
}
…
Or alternatively, you can reset ARGC after having read all arguments :
#!/bin/awk -f
BEGIN {
for (i=0; i<ARGC; i++) {
print ARGV[ARGC-1];
}
ARGC=2;
}
…
Both methods will correctly process myawkscript.awk foobar foo bar … as if foobar was the only file to process (of course you can set ARGC to 3 if you want the two first arguments as files, etc.). In your particular case, it seems you don't want to process any file, so you would set ARGC to 1.
Use nawk or /usr/xpg4/bin/awk. These are newer versions of awk that support more features.
Alternatively, you can install another version of awk like mawk or GNU awk.
A possible work around - maybe not acceptable - would be to use the -v option of awk.
awk -v arg1=foo 'BEGIN { print arg1; }'

unable to run awk command as a shell script

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)

Resources