need example for awk command and awk within awk command in in shell script - shell

I need a simple working example that makes me understand
1, awk command in shell script.
2, awk withing awk command in shell script.

I'm not really sure what the point is, but here's awk calling awk from within a shell script...
#!/bin/sh
cmd='BEGIN {print \"foo\"}'
echo foo |
awk "{ system( \"awk '$cmd'\" )}"

Related

Is it possible to pass a script to awk inside a shell variable?

Is it possible to store an awk script inside a shell variable; for example:
export script="'{printf(\$2); printf("\"\\n\"");}'"
echo $script
'{printf($2); printf("\n");}'
The script functions properly when I call it directly as such:
awk '{printf($2); printf("\n");}' testFile.txt
prints proper output
When I try and pass the script as a shell variable, I run into issues.
awk $script testFile.txt
awk: syntax error at source line 1
context is
>>> ' <<<
missing }
awk: bailing out at source line 1
I get a slightly different error when I wrap the variable in double quotes
awk "$script" testFile.txt
awk: syntax error at source line 1
context is
>>> ' <<<
awk: bailing out at source line 1
I'm still learning exactly how shell expansions work, I would appreciate any suggestions about what I am missing here.
Error in your quoting
export script='{printf($2); printf("\n");}'
awk "${script}" YourFile
I am not sure about the proper answer to this, but a very ugly (and probably unstable depending on the $script contents) workaround would be:
echo $script | awk '{print "awk "$0" testFile.txt"}' | bash
This is just printing the contents of $script in an awk statement that is then executed by bash. I am not particularly proud of this, but maybe it helps!
When you type
awk '{printf($2); printf("\n");}' testFile.txt
awk only sees {printf($2); printf("\n");} -- the shell removes the quotes
(see Quote Removal in the bash manual)
Heed #NeronLeVelu's answer.

Self-contained awk script: Saving to file, calling file

For a lab, I wrote a shell script that used awk to do some stuff. Rereading the lab's directions, it seems that I was supposed to write a self-contained awk script. I'm working on translating my bash script into awk, and I'm having a problem right now:
I want to save the output of an awk command to a new file, and then I want to use that output as input for another awk command.
In my bash script, I have this:
awk '/Blocked SPAM/' maillog > spamlog
cat spamlog | awk '{print $0}' RS=' '
It takes all the lines from maillog that contain the string "Blocked SPAM" and saves this to a new file titled spamlog. Then it opens spamlog and replaces every space character ' ' with a new line.
For my awk script, maillog is the file that is passed to the script from shell. My attempt at writing analogous code:
/Blocked SPAM/ > spamlog`
-f spamlog {print $0} RS=' '
I don't really know what I'm doing with my awk script since I'm having trouble finding useful resources for self-contained awk scripts.
awk '/Blocked SPAM/{ print > "spamlog"; gsub( " ","\n"); print }' maillog
Personally, I prefer to invoke that directly from a shell script, but you can easily make it an awk script by writing:
#!/usr/bin/awk -f
/Blocked SPAM/{ print > "spamlog"; gsub( " ","\n"); print }
Invoke that script with 'maillog' as an argument.

Problems reading a system file with awk

I am trying to execute a shell script in which I am trying to open the file /sys/class/power_supply/BAT0/status through awk. But, the script fails to execute saying that the file cannot be read. Even executing the script with sudo does not work. Below is the script. I am on Kubuntu 13.10. I searched a lot, but couldn't find a solution. Thanks for the help!
#!/bin/sh
awk '{
echo $0
}' | /sys/class/power_supply/BAT0/status
The general form of an awk command is:
awk '<awk script commands>' input-file
As status is the input file it should follow the awk scripting. The pipe symbol does not make sense here.
#!/bin/sh
awk '{
print $0
}' /sys/class/power_supply/BAT0/status

How to put punctuation quotation in Awk command?

I am new to awk.I just try to write some thing that to exchange my text file.but I failed.
I want to output like 'hello'.
I used command awk '{print "'hello'"}' filename to do it.but failed:
output like: hello
but I used command awk '{print "\'hello\'"}' filename to do it.failed again:
output like: >
ok.it seems that the awk command do not get what I mean.
So I am confused about that .how to solve the problem.
guys thanks.
Using the ascii code:
awk '{print "\x27" "hello" "\x27"}' filename
Using a variable:
awk -v q="'" '{print q "hello" q}' filename
Example:
$ seq 2 > filename
$ awk '{print "\x27" "hello" "\x27"}' filename
'hello'
'hello'
$ awk -v q="'" '{print q "hello" q}' filename
'hello'
'hello'
Simply use double quotes:
awk "{print \"'hello'\"}" filename
Although that won't really modify your file.
awk '{print "'"'"'hello'"'"'"}' filename
clyfish's answer works, if you must have it output single quotes and you must use scripts that you pass on the command line.
What I usually do in cases like these, though, when I need to do quoting but I don't want to write a 'real' awk script, is this:
awk 'function q(word) { return "\"" word "\"" }
{ printf("mv %s SomeDir/;", q($0)) }'
What I've done is to define a function that returns whatever you pass it in double quotes. Then use printf to actually use it. Without doing that, I would have had to do:
awk '{ print("mv \"" $0 "\" SomeDir/;") }';
It gets pretty nasty. For more complicated examples, this can be a life saver.
However, suppose you really do need to output something with actual single quotes. In that case dealing with odd shell quoting rules while trying to pass scripts like this on the command line is going to drive you completely insane, so I would suggest you just write a simple throwaway file.
#!/usr/bin/awk
# hi.awk
{ print("'hello'") }
then call it:
awk -f ./hi.awk
You don't really even need the #! line in the file if you do it that way, but neither does it hurt.

how to pre-construct awk statement to pass to awk on command line?

I have a shell script that constructs an awk program as a string then pass that string to awk. This is because I want to use values of shell variables in the awk program.
My code looks like this:
awk_prog="'{if (\$4~/$shell_var/) print \$1,\$2}'"
echo $awk_prog
awk $awk_prog $FILENAME
However, when I pass the string to awk, I always get the error:
'{if ($4~/regex/) print $1,$2}'
awk: '{if
awk: ^ invalid char ''' in expression
What does that error message mean? I tried the -F: switch but it does not help. How can I settle this issue?
Thank you.
This is caused by shell quoting. The following will work:
awk_prog="{ if (\$4 ~ /$shell_var/) print \$1, \$2 }"
echo "$awk_prog"
awk "$awk_prog" $FILENAME
When you run awk '{ print }' foo from the command line, the shell interprets and removes the quotes around the program so awk receives two arguments - the first is the program text and the second is the filename foo. Your example was sending awk the program text '{if ...}' which is invalid syntax as far as awk is concerned. The outer quotes should not be present.
In the snippet that I gave above, the shell uses the quotes in the awk_prog= line to group the contents of the string into a single value and then assigns it to the variable awk_prog. When it executes the awk "$awk_prog"... line, you have to quote the expansion of $awk_prog so awk receives the program text as a single argument.
There's another way to get your shell variable into awk -- use awk's -v option:
awk -v pattern="$shell_var" '$4 ~ pattern {print $1, $2}' "$FILENAME"
Use -v multiple times if you have several variables to pass to awk.
If you truly want to hold your awk program in a shell variable, build it up using printf:
awk_script="$( printf '$4 ~ /%s/ {print $1, $2}' "$shell_var" )"
awk "$awk_script" "$FILENAME"
Note the use of quotes in the printf command: single quotes around the template to protect the dollar signs you want awk to interpret, double quotes for shell variables.
Another (IMO simpler) solution which (I think) addresses what you are intuitively trying to do is simply to use eval. You want the shell to behave as if you had literally typed:
awk '{if ($4~/foo/) print $1,$2}' path
(where foo and path are the literal contents of $shell_var and $FILENAME). To make that happen, just slap an eval on the front of your last line (and perhaps quotes for good measure, but they aren't necessary in this case) so that your last line is:
eval "awk $awk_prog $FILENAME"

Resources