[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: inconsistent output for field reference for a number stored as a str
From: |
Andrew J. Schorr |
Subject: |
Re: inconsistent output for field reference for a number stored as a string |
Date: |
Sun, 7 Jun 2020 20:38:21 -0400 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
Hi,
On Sun, Jun 07, 2020 at 04:59:59PM -0400, Ed Morton wrote:
> Using:
>
> $ gawk --version
> GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
>
> I'd have expected all of these to produce the same output:
>
> $ echo 'a b c' | awk '{print $("2")}'
> b
> $ echo 'a b c' | awk '{print ($"2")}'
> b
> $ echo 'a b c' | awk '{print $("2")}'
> b
> $ echo 'a b c' | awk '{printf "%s\n", $"2"}'
> b
> $ echo 'a b c' | awk '{a=$"2"; print a}'
> b
> $ echo 'a b c' | awk '{print $"2"}'
> a b c
>
> but as you can see that last one doesn't and I don't know why. Is it
> a bug or, if not, what's the explanation?
That's very weird. Who would ever think to write $"2" instead of $2?
It seems like it must be a bug though to treat {printf "%s\n", $"2"}
and {print $"2"} differently. In my view, it should either be a syntax error
in both cases, or it should work the same way. It seems to me like a bug
in the parser, since the debugger prints this dump for the last one:
bash-4.2$ cat /tmp/test.awk
{print $"2"}
bash-4.2$ ./gawk -D -f /tmp/test.awk
gawk> dump
[ :0x23f11e8] Op_newfile : [target_jmp = 0x23efe28]
[target_endfile = 0x23efe50]
[target_get_record = 0x23efea0]
[ :0x23efe78] Op_no_op :
[ :0x23f0030] Op_after_beginfile :
[ :0x23efea0] Op_get_record : [target_newfile = 0x23f11e8]
# Rule
[ 1:0x23f2688] Op_rule : [in_rule = Rule] [source_file =
/tmp/test.awk]
[ 1:0x23efef0] Op_K_print_rec : [redir_type = ""]
[ :0x23eff68] Op_no_op :
[ :0x23f0008] Op_jmp : [target_jmp = 0x23efea0]
[ :0x23efe50] Op_no_op :
[ :0x23effe0] Op_after_endfile :
[ :0x23efe28] Op_no_op :
[ :0x23efec8] Op_atexit :
[ :0x23eff40] Op_stop :
There's simply no mention of 2 in the parsed code. Whereas {printf "%s\n", $"2"}
looks like this:
gawk> dump
[ :0x1af61e8] Op_newfile : [target_jmp = 0x1af4e28]
[target_endfile = 0x1af4e50]
[target_get_record = 0x1af4ea0]
[ :0x1af4e78] Op_no_op :
[ :0x1af50a8] Op_after_beginfile :
[ :0x1af4ea0] Op_get_record : [target_newfile = 0x1af61e8]
# Rule
[ 1:0x1af76c8] Op_rule : [in_rule = Rule] [source_file =
/tmp/test2.awk]
[ 1:0x1af4f18] Op_push_i : "%s\n" [MALLOC|STRING|STRCUR]
[ 1:0x1af4fb8] Op_push_i : "2" [MALLOC|STRING|STRCUR]
[ 1:0x1af4f90] Op_field_spec :
[ 1:0x1af4ef0] Op_K_printf : [expr_count = 2] [redir_type = ""]
[ :0x1af4f68] Op_no_op :
[ :0x1af5080] Op_jmp : [target_jmp = 0x1af4ea0]
[ :0x1af4e50] Op_no_op :
[ :0x1af5058] Op_after_endfile :
[ :0x1af4e28] Op_no_op :
[ :0x1af4ec8] Op_atexit :
[ :0x1af4fe0] Op_stop :
And the simple version without the quotes {print $2} gives:
gawk> dump
[ :0x1e931e8] Op_newfile : [target_jmp = 0x1e91e28]
[target_endfile = 0x1e91e50]
[target_get_record = 0x1e91ea0]
[ :0x1e91e78] Op_no_op :
[ :0x1e92080] Op_after_beginfile :
[ :0x1e91ea0] Op_get_record : [target_newfile = 0x1e931e8]
# Rule
[ 1:0x1e94688] Op_rule : [in_rule = Rule] [source_file =
/tmp/test3.awk]
[ 1:0x1e91f40] Op_push_i : 2 [MALLOC|NUMCUR|NUMBER|NUMINT]
[ 1:0x1e91f18] Op_field_spec :
[ 1:0x1e91ef0] Op_K_print : [expr_count = 1] [redir_type = ""]
[ :0x1e91f90] Op_no_op :
[ :0x1e92058] Op_jmp : [target_jmp = 0x1e91ea0]
[ :0x1e91e50] Op_no_op :
[ :0x1e92030] Op_after_endfile :
[ :0x1e91e28] Op_no_op :
[ :0x1e91ec8] Op_atexit :
[ :0x1e91fb8] Op_stop :
I don't have time to dive into awkgram.y at the moment. Arnold's the only
one courageous enough to touch that code. :-)
Regards,
Andy