Unix awk what does f=1 do - unix

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

Related

Output only specific lines in unix

I'm trying to remove lines from the output that contains "xyz" in 1st column using awk as
grep -H --with-filename "Rule" *| awk '$1!=" \*xyz\* "{print $0}'
but I'm not having any success with this.
For example after doing grep -H --with-filename "Rule" I'm getting the output as
file_xyz.log abc p12r
file1.log asd ef23t
fi_xyz.log gbc or26r
file1.log asd ef2t
but I want to remove all lines which contain xyz.
Some notes on your question:
What you have isn't very close to valid awk syntax, you should find an intro to awk tutorial or read a few pages of the manual to get started. I highly recommend everyone get the book Effective Awk Programming, 4th Edition, by Arnold Robbins.
A glance at the grep man page will tell you that -H and --with-filename are the short and long versions of exactly the same option - you don't need to use both, just one of them.
The string Rule doesn't appear anywhere in the output you say you get when grep-ing for Rule and grep -H will output a : after the file name while you show a blank - make sure your input, output, and code are consistent and correct when asking a question.
The approach you're trying to use will fail for filenames that contain spaces.
You never need grep when you're using awk.
This is probably all you need:
awk '(FILENAME !~ /xyz/) && /Rule/{print FILENAME, $0}' *
but there are also ways in some shells (see https://unix.stackexchange.com/q/164025/133219 and https://unix.stackexchange.com/q/335484/133219 for bash examples) to specify a globbing pattern that excludes some strings so then you never open them to search inside in the first place.
try
grep -H --with-filename "Rule" *| awk '$1 !~ /xyz/'

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.

Use Awk script from shell to search into a text file

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

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; }'

How do you split a file base on a token?

Let's say you got a file containing texts (from 1 to N) separated by a $
How can a slit the file so the end result is N files?
text1 with newlines $
text2 $etc... $
textN
I'm thinking something with awk or sed but is there any available unix app that already perform that kind of task?
awk 'BEGIN{RS="$"; ORS=""} { textNumber++; print $0 > "text"textNumber".out" }' fileName
Thank to Bill Karwin for the idea.
Edit : Add the ORS="" to avoid printing a newline at the end of each files.
Maybe split -p pattern?
Hmm. That may not be exactly what you want. It doesn't split a line, it only starts a new file when it sees the pattern. And it seems to be supported only on BSD-related systems.
You could use something like:
awk 'BEGIN {RS = "$"} { ... }'
edit: You might find some inspiration for the { ... } part here:
http://www.gnu.org/manual/gawk/html_node/Split-Program.html
edit: Thanks to comment from dmckee, but csplit also seems to copy the whole line on which the pattern occurs.
If I'm reading this right, the UNIX cut command can be used for this.
cut -d $ -f 1- filename
I might have the syntax slightly off, but that should tell cut that you're using $ separated fields and to return fields 1 through the end.
You may need to escape the $.
awk -vRS="$" '{ print $0 > "text"t++".out" }' ORS="" file
using split command we can split using strings.
but csplit command will allow you to slit files basing on regular expressions as well.

Resources