3

I have written a very simple awk script that reverses every word of a file-:

awk '
{
for (i=1;i<=NF;i++)
{ x=""
for(j=length($i);j>0;j--)
x=x substr($0,j,1);
print x
}}' file1

The contents of file1 is as follows-:

hello

Now what baffles me is that when I replace -:

print x

with

print $x

I get the output of the record ie. I get hello not the reversed output that olleh.

Why is using $x giving me the contents of $0 ? How do variables work in awk ? Its really confusing. Is there a set rule when I am suppose to use $x and when just x ?

8

x is your awk variable, $x is something different....

$0 corresponds to the input string contents of the line just read, while $1...$n correspond to the breakdown fields of $0 contents using the default separator.

awk lets you to programmatically access the fields using a variable, i.e., if the variable MyValue contains 5, $MyValue is the same as $5.

What happens here is that your variable x does contain the olleh string, which numerically is interpreted as 0. In awk, all strings beginning with non-numeric values when used as numeric values are interpreted as 0, e.g., 5*"test" evaluates to 0 because "test" interpreted as 0). So, in your case, $x is the same as $0, which is the input string provided, i.e., hello.

  • Then according to what you have said shouldn't $x be evaluated to 0 and not $0. If it is 0 then shouldn't I get an error ? – Sreyan Nov 23 '14 at 16:19
  • @Marcelo: When Field number expression evaluated to anything other than non-negative integer, the behavior is unspecified. See my answer. – cuonglm Nov 23 '14 at 17:19
  • @Sreyan, actually not. In awk $... is always a field reference. In this case, x evaluated first and taken as numeric. Any string not beginning with numbers in awk, when taken as numbers for whatever reason, is interpreted as zero. – Marcelo Nov 23 '14 at 21:51
  • I mean $... is always a field reference for values >= 1 or the entire input buffer (the line just read) for the value 0. (A note just for the sake of correctness) – Marcelo Nov 23 '14 at 22:02
  • As @cuonglm mentions below (and refers to the POSIX awk specs) the gawk (GNU awk) behavior may not be the same in other implementations of awk, so, one should not expect that $x, when x contains a non-numeric-convertible string value, to always evaluate as $0, but to a undefined value. This, though, do not invalidates the explanation of the experienced behavior that motivated the question. Thanks cuonglm for pointing that out. – Marcelo Nov 24 '14 at 2:09
2

First you should know what is valid variable in awk. POSIX defined awk variable as:

An operand that begins with an <underscore> or alphabetic character from the portable character set (see the table in XBD Portable Character Set), followed by a sequence of underscores, digits, and alphabetics from the portable character set, followed by the '=' character, shall specify a variable assignment rather than a pathname

So, when you have an awk variable x, and you want to use x, just reference it, by writing x directly, example print x or y = x.

When you use $x, you are accessing awk Field variables. In awk, Field variables are accessed, by a $, followed by a number or numerical expression. So when you writing $x, awk will evaluate x first. If x had numeric value, like 1, the statement become $1, awk will give you the value of first field variable. Or you have an numeric expression like (1+1), then $(1+1) become $2, you will get the value of second field variable.

A note that, when field number expression evaluated to anything other than non-negative integer, the behavior is unspecified (like x = "qwerty" or x = "qwerty"+1, then accessing $x is unspecified):

The effect of the field number expression evaluating to anything other than a non-negative integer is unspecified; uninitialized variables or string values need not be converted to numeric values in this context

In your case, your awk implementation had evaluate field number expression (which is a string) to 0, so you got the value of $0 variable. In other awk implementation, the result can be different (At least in OpenBSD awk, you will get an error illegal field).

  • @cuonglm, for field variables, strings contained by awk variables are converted to numbers during their evaluation. Strings that do not begin with digits, when taken as numeric inputs for expressions are converted to 0. The same is not valid for uninitialized variables, though, where the results are indeed unspecified. – Marcelo Nov 23 '14 at 21:56
  • @Marcelo: No, it's not specified by POSIX. As my answer shown The effect of the field number expression evaluating to anything other than a non-negative integer is unspecified; uninitialized variables or string values need not be converted to numeric values in this context. – cuonglm Nov 24 '14 at 1:24
  • @cuonglm, thanks for clarifying. It seems I described what may be the gawk implementation. There is no need to yell, though. – Marcelo Nov 24 '14 at 1:49
  • @Marcelo: Oh, it's not yelling, just want to emphasis. – cuonglm Nov 24 '14 at 1:50
  • @cuonglm. This is just a way of saying that bold is sometimes considered offensive, in special in long sentences, but that's ok, I'm sure this was not you intention. – Marcelo Nov 24 '14 at 2:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.