AWK:使用内联if-then-else的健壮方法
我经常使用内联if-then-else语句AWK:使用内联if-then-else的健壮方法,awk,Awk,我经常使用内联if-then-else语句(…?…:…)将输入文件的字段与分隔符(逗号、冒号、分号…)连接在一起 典型的用例是使用输入文件的字段构建字符串,并将该字符串存储在数组中,如下所示: $ cat file a 1 b 2 a 3 c 1 b 26 c 4 c 2 为了转置这样的文件,我使用以下awk脚本: awk '{a[$1]=a[$1](a[$1]?",":"")$2}END{for(i in a) printf "%s:%s\n",i,a[i]}' file 这种使用inli
(…?…:…)
将输入文件的字段与分隔符(逗号、冒号、分号…)连接在一起
典型的用例是使用输入文件的字段构建字符串,并将该字符串存储在数组中,如下所示:
$ cat file
a 1
b 2
a 3
c 1
b 26
c 4
c 2
为了转置这样的文件,我使用以下awk脚本:
awk '{a[$1]=a[$1](a[$1]?",":"")$2}END{for(i in a) printf "%s:%s\n",i,a[i]}' file
这种使用inline if-then-else的方法不够健壮,我应该使用这种方法:
awk '{a[$1]=($1 in a?a[$1]",":"")$2}END{for(i in a) printf "%s:%s\n",i,a[i]}' file
显然,对于这个简单的输入文件,两个脚本的结果是相同的
那么为什么第二个脚本会更“健壮”
实际上,我正在寻找一个输入示例,它会使第一个脚本失败,而不会使另一个脚本失败。首先,我猜您在第一个awk单行程序中又添加了一个
a[$1]=
。应该是:
awk '{a[$1]=a[$1](a[$1]?",":"")$2}....
我想你的问题是为什么在一个中检查$1要比检查一个[$1]
好。这两个一行程序都适用于您的输入。因为字符串串联使a[$1]
变成了字符串。对于字符串,如果它不是空的,awk将把它计算为true
。也适用于字符串“0”
但是,如果您必须以数字的形式处理输入以适应所需的输出,那么这两种布尔检查可能会有所不同。如果一个数字是0
,awk将计算为false
看看这个例子:
kent$ awk 'BEGIN{if(0)print "number"; if("0")print "string"}'
string
你看,只有后面的那一张被打印出来了
因此,a
中的$1更好,因为无论a[$1]
存储一个数字或字符串,它都将始终工作
但是,如果您在代码中设置了a[$1]
,并且100%确定布尔值a[$1]
将给出您期望的值,则可以使用if(a[$1])
检查。例如,您在代码中进行了字符串连接“$2
。或者您可以设置类似于a[$1]=1
一般<代码> < /COD>中的1美元更好。
< P>除了@ Kent所提到的之外,考虑到一般字段可以是空字符串。提示您当前问题的有CSV输入,因此,现在让我们再次使用该输入,以获得比空间分隔更好的可见性:
$ cat file
a,1
b,
a,3
c,
b,26
c,4
c,2
$ awk -F',' '{a[$1]=a[$1](a[$1]?",":"")$2}END{for(i in a) printf "%s:%s\n",i,a[i]}' file
a:1,3
b:26
c:4,2
$ awk -F',' '{a[$1]=($1 in a?a[$1]",":"")$2}END{for(i in a) printf "%s:%s\n",i,a[i]}' file
a:1,3
b:,26
c:,4,2
另一件事是,if(a[$1])
实际上会向索引为$1
的a
数组添加一个条目,而中的$1则不会。在某些情况下,这可能是内存问题,甚至可能影响程序的逻辑。FYIinline if-then-else语句
=三元表达式
。看:这里的答案都没有回答你的问题吗?如果您有后续问题,请让我们知道,否则请查看下一步要做什么。