微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AWK:使用类似于 FNR==NR 方法的方法连接和处理三个或更多文件

如何解决AWK:使用类似于 FNR==NR 方法的方法连接和处理三个或更多文件

因为我正在学习awk;我发现 FNR==NR 方法是处理两个文件的一种非常常见的方法。如果FNR==NR;那么它是 first file,当 FNR 在读取连接文件的每一行时重置为 1 时,它意味着 !(FNR==NR),它显然是 second file。>

当涉及到 三个 或更多文件时,我看不到第二个和第三个文件的方式,因为它们具有相同的 !(FNR==NR) 条件。这让我试图弄清楚怎么会有 FNR2FNR3 之类的东西?

所以我实现了一种方法来在一个 awk 中处理三个文件。假设每个文件都有 FNR1 FNR2 FNR3。对于我制作的每个单独运行的文件 for loop。每个循环 NR==FNR# 的条件都相同,实际上得到了我的预期:

所以我想知道是否有更多简洁、简洁的方法可以使用以下awk代码

提供类似的结果

示例文件内容

$ cat file1
X|A1|Z
X|A2|Z
X|A3|Z
X|A4|Z
$ cat file2
X|Y|A3
X|Y|A4
X|Y|A5
$ cat file3
A1|Y|Z
A4|Y|Z

AWK for 循环

    $ cat fnrarray.sh 
awk -v FS='[|]' '{ for(i=FNR ; i<=NR && i<=FNR && NR==FNR; i++)         {x++; print "NR:",NR,"FNR1:",i,"FNR:",FNR,"\tfirst file\t"}
                   for(i=FNR ; i+x<=NR && i<=FNR && NR==FNR+x; i++)     {y++; print "NR:","FNR2:",i+x,"\tsecond file\t"}
                   for(i=FNR ; i+x+y<=NR && i<=FNR && NR==FNR+x+y; i++) {print "NR:","FNR3:",i+x+y,"\tthird file\t"}
}' file1 file2 file3 

当前和所需的输出

$ sh fnrarray.sh
NR: 1 FNR1: 1 FNR: 1    first file  
NR: 2 FNR1: 2 FNR: 2    first file  
NR: 3 FNR1: 3 FNR: 3    first file  
NR: 4 FNR1: 4 FNR: 4    first file  
NR: 5 FNR2: 5 FNR: 1    second file 
NR: 6 FNR2: 6 FNR: 2    second file 
NR: 7 FNR2: 7 FNR: 3    second file 
NR: 8 FNR3: 8 FNR: 1    third file  
NR: 9 FNR3: 9 FNR: 2    third file

您可以看到 NRFNR# 对齐,并且可以读取哪个 NR 对应哪个 file#


另一种方法

我在FNR==1{++f} f==1 {}这里Handling 3 Files using awk找到了这个方法

但是这个方法在每次读取新行时替换 arr1[1]

失败尝试 1

$ awk -v FS='[|]' 'FNR==1{++f} f==1 {split($2,arr); print arr1[1]}' file1 file2 file3 
A1
A2
A3
A4

for 循环成功arr1[1] 未更改)

$ awk -v FS='[|]' '{for(i=FNR ; i<=NR && i<=FNR && NR==FNR; i++) {arr1[++k]=$2; print arr1[1]}}' file1 file2 file3 
A1
A1
A1
A1

解决方法

无论如何使用 GNU awk 按顺序识别文件:

  changeField3() {
   
    this.MyItem.field3 = this.MyItem.field2 + ' modification field 3'; 
  }

例如从您提供的 3 个示例输入文件中获取问题中“输出”下的文本:

awk '
    ARGIND == 1 { do 1st file stuff }
    ARGIND == 2 { do 2nd file stuff }
    ARGIND == 3 { do 3rd file stuff }
' file1 file2 file3

或者使用任何 awk 如果所有文件名都是唯一的,无论它们中的任何一个是否为空:

awk '
    ARGIND == 1 { pos = "first" }
    ARGIND == 2 { pos = "second" }
    ARGIND == 3 { pos = "third" }
    { print "NR:",NR,"FNR" ARGIND ":","FNR:",FNR,pos " file" }
' file1 file2 file3
NR: 1 FNR1: 1 FNR: 1 first file
NR: 2 FNR1: 2 FNR: 2 first file
NR: 3 FNR1: 3 FNR: 3 first file
NR: 4 FNR1: 4 FNR: 4 first file
NR: 5 FNR2: 5 FNR: 1 second file
NR: 6 FNR2: 6 FNR: 2 second file
NR: 7 FNR2: 7 FNR: 3 second file
NR: 8 FNR3: 8 FNR: 1 third file
NR: 9 FNR3: 9 FNR: 2 third file

或者如果文件不为空,那么是否唯一(注意在参数列表中 awk ' FILENAME == ARGV[1] { do 1st file stuff } FILENAME == ARGV[2] { do 2nd file stuff } FILENAME == ARGV[3] { do 3rd file stuff } ' file1 file2 file3 两次):

file1

如果文件名可以在 arg 列表中多次出现并且某些文件可能为空,那么使用非 GNU awk 会变得更加棘手,这就是 GNU awk 具有 ARGIND 的原因,例如类似(未经测试):

awk '
    FNR == 1 { argind++ }
    argind == 1 { do 1st file stuff }
    argind == 2 { do 2nd file stuff }
    argind == 3 { do 3rd file stuff }
' file1 file2 file1
,

当涉及到三个或更多文件时,我看不出哪个是第二个 和第三个文件都具有相同的 !(FNR==NR) 条件。这个使 我想弄清楚怎么会有像 FNR2 和 FNR3 这样的东西?

示例如下:

$ cat f1
X|A1|Z
X|A2|Z
X|A3|Z
X|A4|Z

$ cat f2
X|Y|A3
X|Y|A4
X|Y|A5

$ cat f3
A1|Y|Z
A4|Y|Z

示例输出:

$ awk -F '|' 'FNR==1{file++}{array[file,FNR]=$0; max=max>FNR?max:FNR}END{for(f=1; f<=file; f++){ for(row=1; row<=max; row++){ key=f SUBSEP row; if(key in array)print "file: "f,"row :"row,"record: "array[key]   } }}' f1 f2 f3
file: 1 row :1 record: X|A1|Z
file: 1 row :2 record: X|A2|Z
file: 1 row :3 record: X|A3|Z
file: 1 row :4 record: X|A4|Z
file: 2 row :1 record: X|Y|A3
file: 2 row :2 record: X|Y|A4
file: 2 row :3 record: X|Y|A5
file: 3 row :1 record: A1|Y|Z
file: 3 row :2 record: A4|Y|Z

说明:

awk -F '|' 'FNR==1{                   # FNR will reset for every file
              file++                  # so whenever FNR==1 increment variable file
            }
            {
              # array name      : array
              # array key being : file,FNR
              # array value     : $0 which current record/row
              array[file,FNR] = $0; 
              # here we find which row count in all available files
              max = max > FNR ? max : FNR
            }

            END{                     # end block when all files are read
             # start iterating over file
             # as we now variable file hold total no files read
             for(f=1; f<=file; f++)
             { 
                  # iterate now for record from each file
                  # variable max holds max row count
                  for(row=1; row<=max; row++)
                  { 
                      # variable key will now have
                      # key = file-number SUBSET row-number
                      key=f SUBSEP row; 
                      # if key exists in array 
                      # print array value
                      if(key in array)
                           print "file: "f,"record: "array[key] 
                  } 
             }
            }' f1 f2 f3

其他选项是使用真正的多维数组,如下所示。 gawk 当然是具体的。

假设文件名是唯一的,否则使用 FNR==1{ file++} 并使用 FILENAME 代替 file

$ awk --version
GNU Awk 4.2.1,API: 2.0 (GNU MPFR 3.1.6-p2,GNU MP 6.1.2)
Copyright (C) 1989,1991-2018 Free Software Foundation.

$ awk -F '|' '{
              true_multi_array[FILENAME][FNR] = $0
            }
            END{
              for(file in true_multi_array)
                for(row in true_multi_array[file]) 
                  print  "file:",file,"row :" row,"record:" true_multi_array[file][row] 
            }' f1 f2 f3
file: f1 row :1 record:X|A1|Z
file: f1 row :2 record:X|A2|Z
file: f1 row :3 record:X|A3|Z
file: f1 row :4 record:X|A4|Z
file: f2 row :1 record:X|Y|A3
file: f2 row :2 record:X|Y|A4
file: f2 row :3 record:X|Y|A5
file: f3 row :1 record:A1|Y|Z
file: f3 row :2 record:A4|Y|Z

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。