【问题标题】:Iterate over list of known characters迭代已知字符列表
【发布时间】:2014-04-12 05:41:42
【问题描述】:

遍历编写程序时已知的字符列表(在本例中,字符为“X”、“Y”、“Z”):

for (i = 1; i <= 3; ++i) {
    c = substr("XYZ", i, 1)
    # do something with the character
}

问题: 有没有更古怪的方法?请注意,这与 this question 不同,因为我要迭代的字符over 不是输入的一部分。

为了把它放在上下文中,我需要计算 X、Y 和 Z 在一行中特定位置上所有行的出现次数。输入应仅包含相同长度行上的 X、Y 和 Z:

$ cat input.txt
XYXXXYZZYXY
XXXYYYZYYZY
YZZZZYZZXZZ
XXZXXYYZXZY

$ foo.awk < input.txt
X 3 2 2 2 2 0 0 0 2 1 0
Y 1 1 0 1 1 4 1 1 2 0 3
Z 0 1 2 1 1 0 3 3 0 3 1

我现在是foo.awk

#!/bin/awk -f
BEGIN {
    FS = ""
}
NR == 1 {
    len = NF
}
{
    for (i = 1; i <= NF; ++i)
        ++profile[$i][i]
}
END {
    for (c = 1; c <= 3; ++c) {
        char = substr("XYZ", c, 1)
        printf "%s", char
        for (i = 1; i <= len; ++i)
            printf " %d", profile[char][i]
        printf "\n"
    }
}

我以前没有使用过 awk,所以可能我的整个方法完全错误。

【问题讨论】:

  • 提供一个示例文本以及从中得到什么会有很大帮助。
  • @Jotne 你当然是对的,我将它添加到问题中。

标签: loops awk gawk


【解决方案1】:

您的脚本看起来不错。这是一个版本,说明了风格上的一些细微变化:

#!/usr/bin/awk -f
BEGIN {
    FS = ""
    split("XYZ",chars,"")
}
{
    for (i = 1; i <= NF; ++i)
        ++profile[$i,i]
}
END {
    for (c=1;c in chars;c++) {
        printf "%s", chars[c]
        for (i = 1; i <= NF; ++i)
            printf " %d", profile[chars[c],i]
        printf "\n"
    }
}

语句split("XYZ",chars,"") 创建一个数组chars,其中包含您的字母。这样,字符就可以通过下标来引用了。

您的脚本使用的是 GNU 扩展的多维数组。在上面的脚本中,我使用标准的awk 方法来获得相同的结果。 (设置为 FS="" 也是一个 GNU 扩展。)

最后,END 中的外部 for 循环已更改为使用 for (c=1;c in chars;c++) ... 扫描数组索引。即使您更改chars 中的元素数量,这也具有工作的优势。缺点是,除非我们将代码复杂化,否则awk 并不能保证索引按顺序出现。

【讨论】:

  • 谢谢!至于for (c in chars),这就是我所拥有的,在我意识到它不一定按初始顺序迭代之前。所以我想一定是for (i = 1; i &lt;= length; ++i)
  • 多维数组不仅是一个扩展,它们还不够新,不能安装在我必须使用的服务器上安装的 gawk 版本中......
  • +1 FYI 设置 FS = "" 也是一个 gawk 扩展,POSIX 未指定行为。 len 变量和关联的NR==1 块不是必需的,因为NF 将在END 部分中设置为最后读取行的值,因此您可以循环到NF 而不是@987654339 @。您也不需要 split() 的第三个参数,因为您使用的与 FS 相同。
  • @Boris 考虑使用for (i = 1; i in chars; ++i) 而不是for (i = 1; i &lt;= length; ++i)length 没有 args 是一个 gawk 扩展,用于提供当前输入记录的长度 ($0),而不是您感兴趣的数组的长度。返回数组中条目数的 length(array) 也是傻瓜扩展。在 END 部分设置的 $0 也是一个 gawk 扩展。 in 运算符是标准 awk。
  • @EdMorton 我将您的改进纳入答案。
猜你喜欢
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 2016-06-27
  • 2011-05-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多