考虑以下目前属于公共领域的功能。
function join(array, start, end, sep, result, i)
{
if (sep == "")
sep = " "
else if (sep == SUBSEP) # magic value
sep = ""
result = array[start]
for (i = start + 1; i <= end; i++)
result = result sep array[i]
return result
}
我想使用此函数连接连续的列,例如$2, $3, $4
,其中开始和结束范围是变量。
但是,为了做到这一点,我必须首先使用如下所示的循环将所有字段转换为数组。
for (i = 1; i <= NF; i++) {
a[i] = $i
}
或者更简短的版本,正如@StevenPenny所提到的那样。
split($0, a)
不幸的是,这两种方法都需要创建一个新变量。
awk是否有以数组形式访问列的内置方式,以便上述手动转换不是必需的?
答案 0 :(得分:0)
没有这样的数组defined in POSIX awk
(唯一的数组类型特殊变量是ARGV
和ENVIRON
)。
gawk
中也不存在,但它添加了PROCINFO
,SYMTAB
和FUNCTAB
特殊数组。您可以使用SYMTAB
数组(gawk-4.1.0功能)在运行时检查所有已定义的变量和类型:
BEGIN { PROCINFO["sorted_in"]="@ind_str_asc" } # automagic sort for "in"
{ print $0 }
END { for (ss in SYMTAB) printf("%-12s: %s\n",PROCINFO["identifiers"][ss],ss) }
(虽然您会发现列表中缺少SYMTAB
和FUNCTAB
,而--dump-variables
也缺少$0
和$1
,但它们会受到设计的特殊处理。
gawk还提供了一些标准的可加载扩展,但是没有实现此功能(并且考虑到NF
,OFS
...,$n
和$1
之间的动态关系,具有相同功能的数组实现起来有点棘手。)
正如Jidder所建议的,一个解决方法是完全跳过数组并使用字段。字段名称没有什么特别之处,变量$(NF-1)
可以像文字fjoin
一样使用(只需要在function fjoin(start,end,sep, result,ii) {
if (sep=="") sep=" "
else if (sep==SUBSEP) sep =""
result=$start
for (ii=start+1; ii<=end; ii++)
result=result sep $ii
return result
}
{ print "2,4: " fjoin(2,4,":") }
这样的表达式中使用大括号作为优先级。这是一个{ {1}}函数适用于字段而不是数组:
$0
(这不会将split()
视为特殊情况)
或者只是使用FS
并且开心,gawk至少保证它的行为与字段拆分相同(假设FIELDWIDTHS
,IGNORECASE
和{{1}}都不是被修改以改变行为。)
答案 1 :(得分:0)
这是我在自己的代码中所做的
function iter0gen() {
PROCINFO["sorted_in"] = "@ind_num_asc"; # skip this for mawk
return split(sprintf("%0"(NF)"d", 0), iter0, //)
}
既然用空串分割是每个bin 1个字符,那么只要分割一个长度等于NF的零串,创建一个名为iter0的数组,就可以了
for (x in iter0) { $(x) = do stuff….. }
这仅适用于需要惰性迭代器的情况。这样做的好处是,由于默认情况下索引从 1 开始,因此您不会在迭代器循环中意外获得 $0。不利的一面是,如果您不小心,您会在分配到任何字段的那一刻将所有输入 FS 切换为 OFS,而这不会代表您预先备份 $0。
如果您只想要列,那么只需使用 split()
执行数组的标准 FS
。如果您正在使用 gawk 并且也想要 seps 数组,则添加不可移植的可选的第 4 个参数。