【问题标题】:Awk - Compare two files, match a field, merge both filesawk - 比较两个文件,匹配一个字段,合并两个文件
【发布时间】:2012-09-13 16:17:24
【问题描述】:

大家好,我需要一些帮助, 我的目标是在 file2 中匹配 find 或匹配 file1 的第一部分

文件1:

\\tempcomputer\c$\test2;test folder;c:\test2
\\tempcomputer\c$\temp;temp folder;C:\temp
\\tempcomputer\c$\unavailablefolder;c:\unavailablefolder

文件2:

\\tempcomputer\c$\test2\;2.777.768 Bytes;11/09/12;11/09/12
\\tempcomputer\c$\temp\;5.400.050.974 Bytes;10/09/12;11/09/12
Error: Invalid property element: \\tempcomputer\c$\unavailablefolder

预期输出:

\\tempcomputer\c$\test2;test folder;c:\test2;2.777.768 Bytes;11/09/12;11/09/12
\\tempcomputer\c$\temp;temp folder;C:\temp;5.400.050.974 Bytes;10/09/12;11/09/12
\\tempcomputer\c$\unavailablefolder;c:\unavailablefolder;Error: Invalid property element: \\tempcomputer\c$\unavailablefolder

我想从 file1 的第一行进行比较:

\\tempcomputer\c$\test2 

在第二个文件上搜索,并从 file1 连接两个文件

\\tempcomputer\c$\test2;test folder;c:\test2 

从文件 2

c:\test2;2.777.768 Bytes;11/09/12;11/09/12

所以第一行是:

\\tempcomputer\c$\test2;test folder;c:\test2;2.777.768 Bytes;11/09/12;11/09/12

第一行的预期结果:

\\tempcomputer\c$\test2;test folder;c:\test2;2.777.768 Bytes;11/09/12;11/09/12 

第二行的预期结果:

\\tempcomputer\c$\temp;temp folder;C:\temp;5.400.050.974 Bytes;10/09/12;11/09/12

第三行的预期结果:

\\tempcomputer\c$\unavailablefolder;c:\unavailablefolder;Error: Invalid property element: \\tempcomputer\c$\unavailablefolder

【问题讨论】:

  • 为了清楚起见,您能否简化输入和预期输出?至少对我来说,目前还不清楚你想要完成什么。
  • 我想比较例如从 file1 的第一行: \tempcomputer\c$\test2 在第二个文件上搜索,并连接两个文件,从 file1 \tempcomputer\c$\test2 ;test 文件夹;c:\test2 和来自 file2 c:\test2;2.777.768 Bytes;11/09/12;11/09/12。所以第一行是:\tempcomputer\c$\test2;test folder;c:\test2;2.777.768 Bytes;11/09/12;11/09/12
  • @Eduardo 是否第二个文件的第一部分以 \; 结尾?还是那是错字?即第一行,是\\tempcomputer\c$\test2\;2...还是\\tempcomputer\c$\test2;2...
  • 这是正确的不是错字第二行的第一部分以\结尾;对于即 \tempcomputer\c$\test2\;2

标签: text awk


【解决方案1】:

如果它是 c00kiemon5ter 表示带有反斜杠的复制粘贴错误,那么对于 File1 中的每一行迭代 File2 是一件简单的事情,我假设你不想要输出时没有找到匹配项。

simple.awk

BEGIN { FS = OFS = ";" }

{ 
  l=$0
  first=$1
  while(getline < "File2") { 
    if(first == $1) {
      print l, $0
      break
    }
  }
}

运行:

awk -f simple.awk File1

在末尾允许一个可选的反斜杠需要更多的工作,但大部分额外的复杂性可以转移到一个函数中:

more-work.awk

function optional_end(s, c) {
  if(c == "")
    c = "\\"
  if(substr(s, length(s)) == c)
    s = substr(s, 1, length(s) - 1)
  return s
}

BEGIN { FS = OFS = ";" }

{ 
  l=$0
  first = optional_end($1)

  while(getline < "File2") {
    if(first == optional_end($1)) {
      print l, $0
      break
    }
  }
}

运行:

awk -f more-work.awk File1

由 c00kiemon5ter 编辑 :3

修订simple.awk
\; first-field-line-endings 和 prints-joins 第三行一起工作。

BEGIN { FS = OFS = ";"; if( file == "") file = "File2" }

{ 
  l=$0
  first=$1
  while(getline < file) { 
    if((idx = index($0, first))) {
      if (idx == 1)
          $1 = l
      else
          $1 = l FS $0
      print
      break
    }
  }
}

编辑 2

输入文件现在可以作为一个选项给出-v file=SOME_FILE;如果没有给出“File2”,例如:

awk -f simple.awk -v file=SOME_FILE File1

【讨论】:

  • 如果您将 simple.awk 中的 if(first == $1) 更改为 if(first "\\" == $1) ,它将作为 more-work.awk 工作
  • 另外,他不想print l, $0,而是print l, $2..$NF。我将编辑您的答案以在新代码块中修复这些问题。
  • 请记住,这仍然不会打印/加入第三行。为此,我们可能应该替换if(first "\\" == $1)。现在会解决这个问题。完成;)
  • 顺便说一句,我希望可以用这个来编辑你的答案。当我的想法基于您的脚本时,我想我只是在原地“修复”它而不是创建另一个答案..这是一个 +1 :P
  • 不用担心。您的最终解决方案返回 OP 列出的结果,而我的仅处理部分问题,可能应该被删除。这取决于您,更正此答案或发布您自己的答案,我将删除此答案。
【解决方案2】:

假设 File2 中的路径末尾没有终端反斜杠,如下:

join -t ';' <(sort File1) <(sort File2)

将输出:

\\tempcomputer\c$\temp;temp folder;C:\temp;5.400.050.974 Bytes;10/09/12;11/09/12
\\tempcomputer\c$\test2;test folder;c:\test2;2.777.768 Bytes;11/09/12;11/09/12

【讨论】:

  • :) 这就是我的想法,但第 3 行不匹配 .. 这不是错字:/
  • 这也假设每一行都会匹配,不是吗?即,如果第二个文件以与第一个文件中的任何内容都不匹配的任意行开头,join 是否处理此问题(如跳过它并从第二行开始正确连接..)?
  • @c00kiemon5ter:它打印匹配的行并跳过不匹配的行。有打印不匹配行的选项和其他输出控制选项。
  • 谢谢,我测试了它,正如你所说的那样有效,但不适用于第三行。我会记住这一点,谢谢
猜你喜欢
  • 1970-01-01
  • 2014-12-25
  • 1970-01-01
  • 2016-12-09
  • 2018-03-04
  • 2016-06-23
  • 2017-10-25
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多