【问题标题】:Comparing split strings inside fields of two CSV files比较两个 CSV 文件的字段内的拆分字符串
【发布时间】:2014-06-13 02:27:49
【问题描述】:

我有一个 CSV 文件 (file1),看起来像这样:

123,info,ONE NAME
124,info,ONE VARIATION
125,info,NAME ANOTHER
126,info,SOME TITLE

还有另一个 CSV 文件 (file2),如下所示:

1,info,NAME FIRST
2,info,TWO VARIATION
3,info,NAME SECOND
4,info,ANOTHER TITLE

我想要的输出是:

1,123,NAME FIRST,ONE NAME
3,125,NAME SECOND,NAME ANOTHER

如果file2 的逗号分隔字段3 中的第一个单词(即:第1 行中的NAME)等于file1 的字段3 中的任何单词,则打印一行格式为:

field1(file2),field1(file1),field3(file2),field3(file1)

每个文件的行数相同,只有当每个文件的行号相同时才会进行匹配。

我知道我可以像这样在 Awk 中拆分字段并获取 field3 中的第一个单词:

awk -F"," '{split($3,a," "); print a[1]}' file

但由于我在 Awk 方面的能力只有中等,我不知道如何处理使用拆分比较两个文件的工作。

我可以像这样在 Python 中做到这一点:

with open('file1', 'r') as f1, open('file2', 'r') as f2:
    l1 = f1.readlines()
    l2 = f2.readlines()
    for i in range(len(l1)):
        line_1 = l1[i].split(',')
        line_2 = l2[i].split(',')
        field_3_1 = line_1[2].split()
        field_3_2 = line_2[2].split()
        if field_3_2[0] in field_3_1:
            one = ' '.join(field_3_1)
            two = ' '.join(field_3_2)
            print(','.join((line_2[0], line_1[0], two, one)))

但我想知道如何在 Awk 中完成这样的工作,因为我偶尔会使用只有 Awk 可用的 shell。

这似乎是一项奇怪的任务,我认为我的示例可能有点令人困惑,但我需要执行此操作以检查其中一个文件中是否存在损坏/格式错误的数据。

【问题讨论】:

  • 为什么 NAME FIRST 匹配 ONE NAME 而不是 NAME ANOTHER?我建议发布一些真实数据以获得更好的答案。
  • @jaypal 因为它们的行号不同。我会更新以澄清。

标签: csv awk


【解决方案1】:
awk -F, -vOFS=, '
{
  num1 = $1
  name1 = $3
  split(name1, words1, " ")
  getline <"file2"
  split($3, words2, " ")
  for (i in words1)
    if (words2[1] == words1[i]) {
      print $1, num1, $3, name1
      break
    }
}
' file1

输出:

1,123,NAME FIRST,ONE NAME
3,125,NAME SECOND,NAME ANOTHER

【讨论】:

  • 对不起,如果我在帖子中不清楚,但它们只有在它们具有相同的行号时才匹配。
  • @JohnB 我明白了。添加另一个小测试可以实现这一点。见编辑。
  • @JohnB 我突然想到,由于您要比较每个文件中的相同行号,因此可以使代码更有效率。见编辑。
  • +1 很好地使用了getline。我会使用循环而不是假设最后一个字段仅包含 2 个单词。再加上-v OFS=,,那么你可以写print $1, num1, $3, name1,这样会更好一点。
  • @glennjackman 好主意。我将它们添加到我的答案中。谢谢!
【解决方案2】:

您可以尝试一些类似的东西,尽管以下内容只为第二个文件中的每一行打印一个匹配项:

 awk -F, 'FNR==NR {
    count= split($3, words, " ");
    for (i=1; i <= count; i++) { 
        field1hash[words[i]]=$1; 
        field3hash[$1]=$3; 
    }
    next;
  }
  {
     split($3,words," "); 
     if (field1hash[words[1]]) { 
         ff1 =  field1hash[words[1]]; 
         print $1","ff1","$3","field3hash[ff1]
      }
  }' file1 file2

【讨论】:

    【解决方案3】:

    我更喜欢@ooga 的回答:

    awk -F, -v OFS=, '
        NR==FNR {
            split($NF, a, " ")
            data[NR,"word"] = a[1]
            data[NR,"id"] = $1
            data[NR,"value"] = $NF
            next
        }
        {
            n = split($NF, a, " ")
            for (i=1; i<=n; i++)
                if (a[i] == data[FNR,"word"])
                    print data[FNR,"id"], $1, data[FNR,"value"], $NF
        }
    ' file2 file1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-31
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      相关资源
      最近更新 更多