【问题标题】:Multiple input files awk command line多个输入文件 awk 命令行
【发布时间】:2016-01-17 02:56:32
【问题描述】:

我是一个 awk 新手,诚然不明白 FNR NR 是如何驱动文件循环的。我能够让两个输入文件正常工作。我需要添加另一个(inputFile3)。

我从命令行运行这个:

awk -f parseField.awk inputFile1.csv inputFile2.csv ./inputFile3.TXT

目前,我使用以下方法遍历 inputFile3:

FNR!=NR {...}

我通过 inputFile1 循环使用:

FNR==NR {...}

我需要添加另一个文件(inputFile2)。我可以在我的 awk 脚本 (parseField) 中使用什么语法来访问第三个输入文件?

【问题讨论】:

  • FNR == "当前输入文件中的输入记录号。" NR == "目前看到的输入记录总数。"所以FNR==NR 对于第一个文件,对于其他每个文件都不同。你想用你的第三个文件做什么?

标签: awk


【解决方案1】:

不像 POSIX FILENAME 解决方案那样优雅,但对于缺少太多功能的尘土飞扬的旧 awks 来说很方便。在将数据发送到awk 之前,您可以通过多种方式创建一个复合语句来操作数据...

选项 1

首先,您可以在发送到awk 的每个文件之前单独输出文件编号。因此,如果您的文件如下所示:

文件1

Line 1 of 1

文件2

Line 1 of 2
Line 2 of 2

文件3

Line 1 of 3
Line 2 of 3
Line 3 of 3

你可以这样做:

{ echo 1; cat file1; echo 2; cat file2; echo 3; cat file3; }
1
Line 1 of 1
2
Line 1 of 2
Line 2 of 2
3
Line 1 of 3
Line 2 of 3
Line 3 of 3

并将其通过管道传输到awk,然后每次字段数为 1 时获取文件编号

{ echo 1; cat file1; echo 2; cat file2; echo 3; cat file3; } | awk 'NF==1{file=$1;next} {print file,$0}'
1 Line 1 of 1
2 Line 1 of 2
2 Line 2 of 2
3 Line 1 of 3
3 Line 2 of 3
3 Line 3 of 3

选项 2

或者,您可以将文件编号编辑到每一行的开头或结尾,以便在awk 中以$1 的形式使用,如下所示:

{ sed 's/^/1 /' file1; sed 's/^/2 /' file2; sed 's/^/3 /' file3; }
1 Line 1 of 1
2 Line 1 of 2
2 Line 2 of 2
3 Line 1 of 3
3 Line 2 of 3
3 Line 3 of 3

所以,现在你可以做

{ sed 's/^/1 /' file1; sed 's/^/2 /' file2; sed 's/^/3 /' file3; } | awk '{file=$1; ...}'

我仍然投票支持@fedorqui 的解决方案 :-)

【讨论】:

    【解决方案2】:

    要添加到@EtanReisner 的好信息,您可以保留一个计数器:FNR==1 {file_number++}。每当读取文件的第一行时,这将增加计数器。

    总而言之,你可以说:

    #!/bin/awk -f
    
    BEGIN {print "start program"}
    NR==1 {print "reading first file"}
    FNR==1 {filenum++; print "I am in file number", filenum}
    { ... }
    

    如果您在 GNU POSIX awk (thanks Jonathan Leffler) 中,您也可以使用 FILENAME 变量。或者ARGC 变量和ARGV 数组。


    另请参阅Idiomatic awk 中的相关信息:

    另外一个在awk中经常用到的构造如下:

    $ awk 'NR == FNR { # some actions; next} # other condition {# other actions}' file1.txt file2.txt
    

    这在处理两个文件时使用。处理多个时 文件,awk 依次读取每个文件,一个接一个,在 它们在命令行上指定的顺序。特殊变量 NR 存储到目前为止读取的输入记录总数,无论 读取了多少文件。 NR 的值从 1 开始并且始终 增加直到程序终止。另一个变量 FNR 存储 从正在处理的当前文件中读取的记录数。这 FNR 的值从 1 开始,一直增加到当前文件的末尾 达到,然后在第一行的第一行再次设置为 1 读取下一个文件,依此类推。所以,条件 NR == FNR 只为真 而 awk 正在读取第一个文件。

    【讨论】:

    • FILENAME 是 POSIX awk 的一部分。 ARGV 数组和 ARGC 变量也是如此——ARGV 的索引从 0(而不是 1)开始,记录的参数不包括 awk 和程序的选项。
    • @JonathanLeffler 是的,这就是为什么我建议在FNR==1 时使用计数器作为最可靠的方法。
    • 我同意FNR == 1 是检测文件更改的好方法。您对 GNU Awk 的评论比需要的更严格(FILENAME 不仅仅在 GNU Awk 中)。知道 ARGC 和 ARGV 的存在会很有帮助。
    • @JonathanLeffler 啊,现在我明白你的意思了。谢谢你,更新了!
    猜你喜欢
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    相关资源
    最近更新 更多