[PLUG] bash and awk strangeness

Micah Cowan micah at addictivecode.org
Tue Jan 27 19:31:37 UTC 2015


Apologies for top posting.

You provided no input to awk in the command expansion. Therefore, awk
will go ahead and slurp from standard input, greedily printing
wtf:$line for each of the lines that _would_ have been read by the
"while read line" part. When the awk program is complete, the while
statement will have no more lines to read, since they will all have
been fed to awk instead.

Also, the $m in the awk statement won't do what you expect. You used
single quotes for the argument to awk, so the shell isn't going to
expand $m. awk will see "$m" literally. Since m has no value, I think
it's equivalent to $0, so awk probably just prints the entire line it
reads in, as opposed to one specific word? Also, if all you want to do
is print a value that you already got in the shell, I don't understand
why you would use awk (which expects to slurp in input), instead of
just using echo or printf or something.

Or maybe you _wanted_ awk to see the $m literally, and expected it to
see the shell's value? In awk, though, $m doesn't mean "expand the
variable $m" (which it wouldn't see anyway, since (a) you didn't
export the variable to the environment, and (b) awk doesn't slurp
things in from the environment automatically). Variables in awk are
expanded just by naming them; the $FOO syntax means "give me field
number FOO from the current line (where FOO is expected to be a
variable containing a number)"

It's very unclear to me what you expected the awk statement to do, but
it's very clear to me that it's not what you actually asked it to do.
:)

Maybe you're just trying to experiment with awk, to understand how it
works? If so, bear in mind that an awk program always automatically
slurps in standard input (unless a file is named as an argument
instead), and processes it linewise. Exactly like sed does (except
that awk is rather more powerful/flexible... though sed is
Turing-complete for what that's worth).

To get awk to just print out the "$m" variable, you'd first have to
export it into awk's environment, and then use the ENVIRON array
within awk to access it. You'd also have to redirect awk's standard
input from /dev/null, so it doesn't read any actual lines, and put the
print statement within a BEGIN block. Something like:

host=$(export m; awk 'BEGIN { print "wtf:" ENVIRON["m"] }' </dev/null)

FWIW, the </dev/null didn't appear to actually be required for me,
perhaps because no line-dependent blocks were given. But I don't know
if it's portable to rely on that, so redirect just to be safe.

Obviously, a pretty awkward way to use awk, though... In general, if
you don't want awk to process its standard input, or a file, then awk
might not be the best choice of language for what you're doing.

Hope that helped!

-mjc

On Tue, Jan 27, 2015 at 9:53 AM, Daniel Herrington <herda05 at gmail.com> wrote:
> All,
>
> I'm clearly doing something wrong, and clearly am missing something about
> bash and awk interaction. My script:
>
> #!/usr/bin/bash
>
> echo "Starting script"
> while read line
> do
>     for m in $line
>     do
>       echo "before testing: $line :: $m"
>       host=$(awk '{ print "wtf:" $m }')
>       echo "$line :: $m :: $host"
>     done
> done < $1
>
> It reads a file and outputs the list of names in the file, and I though
> would be like:
> Starting script
> before testing: foo :: foo
> foo :: foo :: foo
> before testing: bar :: bar
> bar :: bar :: bar
> before testing: baz :: baz
> baz :: baz :: baz
> before testing: bunt :: bunt
> bunt :: bunt :: bunt
>
> However, what I get is:
> Starting script
> before testing: foo :: foo
> foo :: foo :: wtf:bar
> wtf:baz
> wtf:bunt
>
> I have isolated it to the awk command printing out the actual file
> contents. However, I'm not sure how awk is looping through anything, as it
> only should should have access to $line, and $line is a single line from
> the file. It seems like awk is not in the loop?
>
> thanks,
>
> --
> Daniel B. Herrington
> _______________________________________________
> PLUG mailing list
> PLUG at lists.pdxlinux.org
> http://lists.pdxlinux.org/mailman/listinfo/plug



More information about the PLUG mailing list