Running an awk by splitting the lines - shell

This is such a basic question in awk . But I am facing issues in this and I dont know why. problem is when I run the awk command in a single line such as
awk 'BEGIN {} {print $0;}' FILE
Then the code is running perfecctly
But if I split the code between lines such as
awk '
BEGIN
{
}
{
print $0;
}' FILE
It gives me an error stating that BEGIN should have an action part . I was wondering since it is the same code that I am formatting, why am I getting this error. Its really important for me to solve this as I would be writting large lines of codes in awk it would be difficult for me to format and bring it in a single line everytime. Could you ppl please help me regarding this. Thank you. Note. I am running this awk in shell environment

Add the '{' right after theBEGIN` and you will not get the error message.
The opening paren { for BEGIN needs to be on the same line as BEGIN. So change what you have
awk '
BEGIN
{
to
awk '
BEGIN {
and you won't get the error message.
The manual does state that "BEGIN and END rules must have actions;", so that may be another problem. This
awk 'BEGIN {} ...
seems a bit odd to me (and there's really no reason to have this if nothing is happening)
#Birei's helpful comment below explains that the way these statements will "parse will be different in both cases. The open '{' in next line is parsed as an action without pattern (not related with BEGIN), while in same line means an empty action of the BEGIN rule."

Related

Using awk to get lines between two patterns

newbie with awk and trying to write a bash script to use it to print lines between two patterns in a log file and for the life of me I cannot make it work.
I am thinking I need to escape some of the characters.
Here's an example of the section of log I am trying to get lines from:
Processing... AP710 (/var/opt/testsys/rptprint/AP710)
sidjosajdois
sokds3488sds
doskdoskdoskdo
sodk229929
sending entire report to Job Mgr (spool) for user
I want the four lines between the "Processing..." line (first pattern) and the "sending" line (second pattern), and there is only one section of the log that has this above section with both the first pattern line and second pattern line.
I've tried using awk with the following command using a portion of the first pattern, and escaping the "/" characters as needed:
awk '/\/var\/opt\/testsys\/rptprint\/AP710/{flag=1;next}/sending entire report to Job Mgr/{flag=0}flag' log
But it gives me some other different section of the log that also happens to have the path "/var/opt/testsys/rptprint/AP710", so then I tried changing it to have more of the line (first pattern) by adding "Processing..." and it doesn't return anything....
awk '/Processing\.\.\. AP710 \(\/var\/opt\/testsys\/rptprint\/AP710/{flag=1;next}/sending entire report to Job Mgr/{flag=0}flag' log
Can someone give some guidance about awk so I can get the lines between the 2 patterns? After spending a few hours I am going a little bonkers trying to figure it out, I think my being new to awk is causing me to miss something obvious.
Cheers.
Whenever you find yourself escaping characters in a regexp to make them literal, really consider whether or not you should be using a regexp or if instead you should be doing a string comparison. In fact, always start out with a string comparison and switch to regexp if you need to.
$ awk '
$0=="sending entire report to Job Mgr (spool) for user" { inSection=0 }
inSection;
$0=="Processing... AP710 (/var/opt/testsys/rptprint/AP710)" { inSection=1 }
' file
sidjosajdois
sokds3488sds
doskdoskdoskdo
sodk229929

Bash - work with a file in the temp folder

In my script I am creating a temp directory with this command
TMPDIR=$(mktemp -d)
and later when I want to create a file there I use (with $DATA being my source data file)
touch $TMPDIR/data
echo "$DATA" > $TMPDIR/data
command. Later on, I use awk to alter the data with this syntax :
awk '
{ a[i++]= ($0 * '$factor') }
END{
{ for (j=0;j < i;j++) print a[j] }
}
' ${TMPDIR}/data
and then I use gnuplot to plot it. But gnuplot says there are some errors and thus I wanted to print the $TMPDIR/data with cat. But it says the file doesn't exist. What do I do wrong ?
Thanks
I was reading through the unanswered questions and found this one. Later on reading all the comments realized that this is one of the questions already answered in the comments. The issue here was that the user has forgotten to redirect the output from the awk command to a file. To save others from reading the comments and coming to the same conclusion, I am posting this as an answer. Here is the comment which answers the question:
as dumb as it seems to be, lurker was right, I have forgotten to
output the awk into the file I wanted to thank you all for your
comments – Jesse_Pinkman

Need a guide to basic command-line awk syntax

I have read several awk tutorials and seen a number of questions and answers on here and the problem is that I'm seeing a LOT of variety in how people do their awk 1-liners and it has really overcomplicated it in my mind.
So I see things like this:
awk '/pattern/ { print }'
awk '/pattern/ { print $0 }'
awk '/pattern/ { print($0) }'
awk '/pattern/ { print($0); }'
awk 'BEGIN { print }'
awk '/pattern/ BEGIN { print };
Sometimes I get errors and sometimes not but because I'm seeing so many different phrasings I'm really having trouble fixing syntax errors because I can't figure out what's allowed and what isn't.
Can someone explain this? Does print require parens or not? Are semi-colons required or not? Is BEGIN required or not? What happens when you start an awk script with a /pattern/, and/or just pass it the name of a function like print on its own?
One at a time:
Can someone explain this?
Yes.
Does print require parens or not?
print, like return, is a builtin, not a function, and as such does not use parens at all. When you see print("foo") the parens are associated with the string "foo", they are NOT in any way part of the print command despite how it looks. It might be clearer (but still not useful in this case) to write it as print ("foo").
Are semi-colons required or not?
Not when the statements are on separate lines. Like in shell, semi-colons would be required to separate statements that occur on a single line
Is BEGIN required or not?
No. Note that BEGIN is a keyword that represents the condition that exists before the first input file is opened for reading so BEGIN{print} will just print a blank line since nothing has been read to print. Also /pattern/ BEGIN is nonsense and should produce a syntax error.
What happens when you start an awk script with a /pattern/, and/or just pass it the name of a function like print on its own?
An awk script is made up of condition { <action> } sections with the default condition being TRUE and the default action being print $0. So awk '/pattern/' means if the regexp "pattern" exists in the current record then invoke the default action which is to print that record and awk '{ print }' means the default condition of TRUE applies so execute the specified action and print the current record. Not also that print by default prints the current record so print $0 is synonymous with just print.
If you are considering starting to use awk, get the book Effective Awk Programming by Arnold Robbins and at least read the first chapter or 2.
Function calls require (). Statements do not (but appear to allow them).
print and printf are statements so do not require () (but supports it "The entire list of items may be optionally enclosed in parentheses.")
From print we also find out that
The simple statement ‘print’ with no items is equivalent to ‘print $0’: it prints the entire current record.
So we now know that the first three statements are identical.
From Actions we find out that.
An action consists of one or more awk statements, enclosed in curly braces (‘{…}’).
and that
The statements are separated by newlines or semicolons.
Which tells us that the semicolon is a "separator" and not a terminator so we don't need one at the end of an action so we now know the fourth is also identical.
BEGIN is a special pattern and that
[a] BEGIN rule is executed once only, before the first input record is read.
So the fifth is different because it operates once at the start and not on every line.
And the last is a syntax error because it has two patterns next to each other without an intervening action or separator.
All of those awk commands (except the last 2) can be shortened to:
awk '/pattern/' file
since print is always the action in awk.
Semicolon is optional just before }.
You cannot place BEGIN after /pattern/

Printing lines according to their columns in shell scripting

i know it is very basic question but im total new in shell scripting
i a txt file called 'berkay' and content of it is like
03:05:16 debug blablabla1
03:05:18 error blablablablabla2
05:42:14 degub blabblablablabal
06:21:24 debug balbalbal1
I want to print the lines whose second column is error so the output will be
03:05:18 error blablablablabla2
I am thinking about something like " if nawk { $2}" but i need help.
With this for example:
$ awk '$2=="error"' file
03:05:18 error blablablablabla2
Why is this working? Because when the condition is true, awk automatically performs its default behaviour: {print $0}. So there is no need to explicitly write it.

awk exiting the ACTION path and going directly to END part

I am using an awk script and the skeleton of the same is simple
awk '
BEGIN {
Variable declaration
}
{
ACTION PART
}
END
{
}' FILE A
The file A is such a huge file. So I wanted not to traverse the entire file and so what I am trying to do is, I am trying to keep some checks in ACTION PART in such a way that if that check is successful, then I need to skip reading the rest part of the file and directly go to END part.
My question is how would I redirect the script from ACTION PART to END Part based on the condition.. I am looking for some kind of command like "break" in for loop. Could you people share your ideas. Thank you.
The exit command will do what you want.
From the man page:
Similarly, all the
END blocks are merged, and executed when all the input is exhausted (or
when an exit statement is executed).
Use "exit" as it terminates current block, but END is still handled. See example bellow.
$ cat test.input
hello
world
one
$ awk 'BEGIN { print "Start-up"} {print "Read:", $1; if ($1 == "world") {exit}} END {print "Phase-out"}' test.input
Start-up
W: hello
W: world
Phase-out

Resources