最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

awk - How to check if a variable exists and assign it a default value if it doesn't? - Stack Overflow

programmeradmin1浏览0评论

With GNU awk 5.3.1 I want to assign a default value to a variable if it has not been given one on the command line. The value can be anything, including 0. I thought I could use SYMTAB but as SYMTAB is built during the parsing and before the execution it does not work:

$ awk -v v=1 'BEGIN { if(!("v" in SYMTAB)) v = 42; print "v = " v }' /dev/null
v = 1
$ awk 'BEGIN { if(!("v" in SYMTAB)) v = 42; print "v = " v }' /dev/null
v = 

Is there another way?

With GNU awk 5.3.1 I want to assign a default value to a variable if it has not been given one on the command line. The value can be anything, including 0. I thought I could use SYMTAB but as SYMTAB is built during the parsing and before the execution it does not work:

$ awk -v v=1 'BEGIN { if(!("v" in SYMTAB)) v = 42; print "v = " v }' /dev/null
v = 1
$ awk 'BEGIN { if(!("v" in SYMTAB)) v = 42; print "v = " v }' /dev/null
v = 

Is there another way?

Share Improve this question edited Feb 10 at 13:53 Renaud Pacalet asked Feb 10 at 12:37 Renaud PacaletRenaud Pacalet 29.4k3 gold badges41 silver badges59 bronze badges 0
Add a comment  | 

3 Answers 3

Reset to default 5

The way to determine if a variable is set or not in any awk is by comparing it to both 0 and null since the initial value for any scalar variable is 0-or-null, there's no need for a gawk-specific SYMTAB[] lookup (which you've already discovered you can't use for this as the variable v will exist in SYMTAB[] since it's mentioned in your code) or typeof() call. For example:

$ awk -v v=1 'BEGIN { if((v=="") && (v==0)) v = 42; print "v = " v }'
v = 1

$ awk -v v=0 'BEGIN { if((v=="") && (v==0)) v = 42; print "v = " v }'
v = 0

$ awk -v v= 'BEGIN { if((v=="") && (v==0)) v = 42; print "v = " v }'
v =

$ awk 'BEGIN { if((v=="") && (v==0)) v = 42; print "v = " v }'
v = 42

FWIW that's also how you can tell if an optional parameter to a function was passed in or not.

By the way, in addition to portability, there's a functional difference between the above approach and using gawk for typeof(v) == "untyped" as suggested elsewhere:

$ awk 'BEGIN { print "v = " v; if((v=="") && (v==0)) v = 42; print "v = " v }' /dev/null
v =
v = 42

$ awk 'BEGIN { print "v = " v; if(typeof(v) == "untyped") v = 42; print "v = " v }' /dev/null
v =
v =

If you're going to use typeof() for this then you need to check for its output being either untyped or unassigned:

$ awk 'BEGIN { print "v = " v; if(typeof(v) ~ /^un(typed|assigned)$/) v = 42; print "v = " v }' /dev/null
v =
v = 42

See the gawk man page for more information on that :-).

I would exploit typeof function for this task following way

awk -v v=1 'BEGIN{print typeof(v)=="untyped"?"v was not given":"v was given"}' /dev/null
awk 'BEGIN{print typeof(v)=="untyped"?"v was not given":"v was given"}' /dev/null

gives output

v was given
v was not given

(tested in GNU Awk 5.3.1)

If you want a generic method to differentiate between ...

[ A ] The special awk NULL value (both 0 and "")


[ B ] A string-only empty string (""),

[ C ] A numeric-only zero (0 / -0), or


[ D ] None of the above

... that works across all awk variants by eliminating dependencies for typeof() and/or SYMTAB[], you can use this reverse waterfall function I conjured up :

function differentiate_zero_null(_) {

    return (!!_)        ? "D.[" (_) "]-boolean-TRUE" \
         : (_ != (_)_)  ? "C.<" (_) ">-numeric-zero" \
         : (_ < _) != _ ? "B.{" (_) "}-empty-str"    \
                        : "A.(" (_) ")-AWK-NULL"
}
发布评论

评论列表(0)

  1. 暂无评论