【问题标题】:Using AWK to Process Input from Multiple Files使用 AWK 处理来自多个文件的输入
【发布时间】:2013-02-05 17:15:42
【问题描述】:

许多人通过发布以下解决方案来一次对多个输入文件进行 AWK 处理非常有帮助:

$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1

这很好,但我想知道是否有人可以向我解释为什么?我发现 AWK 语法有点难以掌握,并希望有人不介意为我破坏代码 sn-p。

【问题讨论】:

    标签: awk


    【解决方案1】:
    awk 'FNR==NR{a[$1]=$2 FS $3;next}
    

    这里我们处理第一个输入(file2)。比如说,FS是空间,我们向上构建一个数组(a),索引是column1,value是column2 " " column3FNR==NR and next的意思是,这部分代码只对file2起作用。你可以看看什么是 NR 和 FNR

    { print $0, a[$1]}' file2 file1
    

    NR != FNR 是时候处理第二个输入,file1。这里我们打印file1的行,以column1为索引,找出array(a) print中的值。换句话说,file1 和 file2 在两个文件中都由 column1 连接。

    对于 NR 和 FNR,很快,

    1st input has 5 lines
    2nd input has 10 lines,
    
    NR would be 1,2,3...15
    FNR would be 1...5 then 1...10
    

    你看到FNR==NR检查的把戏了。

    【讨论】:

    • 肯特,很好的解释;非常感谢您。我没有意识到“FNR==NR”正在形成一种“if”语句。这正是我前进所需要的。非常感谢您抽出宝贵时间提供帮助!
    • 可以在 awk 脚本文件中写这个单行吗?
    • @Sebastian 是的,有可能。
    【解决方案2】:

    我在 Google 上找到了这个问题/答案,它似乎是指在另一个问题 (How to merge two files using AWK?) 中找到的一个非常具体的数据集。接下来是我一直在寻找的答案(我想大多数人都会这样),即使用 AWK 简单地连接来自两个不同文件的每一行。虽然您可能可以使用一些 UNIX 实用程序,例如 joinpaste,但如果您想要的输出不同,AWK 显然会更加灵活和强大,使用 if 语句,或更改 OFS (根据实用程序,这可能更难做到;见下文)例如,以更具表现力的方式更改输出(对于 shell 脚本编写者来说,这是一个重要的考虑因素.)

    对于简单的逐行连接:

    awk 'FNR==NR { a[FNR""] = $0; next } { print a[FNR""], $0 }' file1 file2

    这通过使用隐式类型转换来模拟数字索引数组(AWK 仅具有关联数组)的功能。它比较有表现力且易于理解。

    使用两个名为 test1 和 test2 的文件,内容如下:

    测试1:

    line one
    line two
    line three
    

    测试2:

    line four
    line five
    line six
    

    我得到这个结果:

    line one line four
    line two line five
    line three line six
    

    根据您希望如何连接输出中的列之间的值,您可以选择适当的输出字段分隔符。这是一个用省略号 (...) 分隔列的示例:

    awk 'BEGIN { OFS="..."} FNR==NR { a[(FNR"")] = $0; next } { print a[(FNR"")], $0 }' test1 test2

    产生这个结果:

    line one...line four
    line two...line five
    line three...line six
    

    我希望这至少能激励大家利用 AWK 的强大功能!

    【讨论】:

    • 如果目标只是并排连接列,使用paste命令会简单很多。
    【解决方案3】:

    不久前,我偶然发现了一个非常好的解决方案,可以同时处理多个文件。方法是使用方法将AWK数组中的文件保存在内存中:

    FILENAME==ARGV[1] {  file2array[FNR] = $0 ; next }
    FILENAME==ARGV[2] {  file1array[FNR] = $0 ; next }
    

    对于后期数据处理,最好是保存行数,所以:

    FILENAME==ARGV[1] {  file2array[FNR] = $0 ; f2rows = FNR ; next }
    FILENAME==ARGV[2] {  file1array[FNR] = $0 ; f1rows = FNR ; next }
    

    f2rowsf1rows 将保留最后一行的位置。

    它有更多的代码,但如果你想要更复杂的数据处理,我认为这是更好的方法。此外,以前的方法按顺序处理输入,因此如果您需要同时进行一些依赖于两个文件中的数据的计算,您将无法做到这一点,而使用这种方法,您可以对两个文件进行所有操作。

    【讨论】:

    • 虽然其他答案非常适合两个文件(或者更多,如果它只是需要特殊处理的第一个文件) - 赞成这个,因为您可以将它与任意数量的文件一起使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 2021-09-18
    • 2020-01-13
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    相关资源
    最近更新 更多