从CSV

时间:2018-01-20 14:24:07

标签: csv awk

我有一个看起来像这样的文件:

64fe12c7-b50c-4f63-b292-99f4ed74e5aa, ip, 1.2.3.4, 
64fe12c7-b50c-4f63-b292-99f4ed74e5aa, ip, 4.5.6.7, 
bacd8a9d-807f-4ae9-95d2-f7cc17222cab, ip, 0.0.0.0/0, silly string
bacd8a9d-807f-4ae9-95d2-f7cc17222cab, ip, 0.0.0.0/0, crazy town
db86d211-0b09-4a8f-b222-a21a54ad2f9c, ip, 8.9.0.1, wild wood
db86d211-0b09-4a8f-b222-a21a54ad2f9c, ip, 0.0.0.0/0, wacky tabacky
611f8cf5-f6f2-4f3a-ad24-12245652a7bd, ip, 0.0.0.0/0, cuckoo cachoo

我想提取一个唯一的GUID列表

  1. GUID在第3列中没有0.0.0.0/0
  2. 第3列匹配0.0.0.0/0并且有多个GUID实例,其中至少有一个匹配不是0.0.0.0/0
  3. 在这种情况下,所需的输出为:

    64fe12c7-b50c-4f63-b292-99f4ed74e5aa
    db86d211-0b09-4a8f-b222-a21a54ad2f9c
    

    试着仔细考虑一下,我觉得我应该制作一个独特的GUID数组/列表,然后点击匹配的行并运行上述两个条件的过程,但我只是不知道用短脚本或者grep / awk / sort / cut one liner来解决这个问题的最佳方法。感谢任何帮助!

    (原始文件是4列csv,其中第4列通常为空)

5 个答案:

答案 0 :(得分:2)

使用awk

awk -F, '$3 !~/0\.0\.0\.0\/0/ && !seen[$1]++{print $1}' infile

<强>解释

  • $3 !~/0\.0\.0\.0\/0/ field3与regexp和(&&
  • 不匹配 之前看不到
  • !seen[$1]++ field1(每当awk看到重复键($1)时,数组值将增加1,我们使用逻辑否定仅打印一次值)
    • !是逻辑否定运算符
    • seen是数组
    • $1是数组键
    • ++增量运算符(当前上下文后增量)
  • print $1 print field1

测试结果:

$ cat infile
64fe12c7-b50c-4f63-b292-99f4ed74e5aa, ip, 1.2.3.4, 
64fe12c7-b50c-4f63-b292-99f4ed74e5aa, ip, 4.5.6.7, 
bacd8a9d-807f-4ae9-95d2-f7cc17222cab, ip, 0.0.0.0/0, silly string
bacd8a9d-807f-4ae9-95d2-f7cc17222cab, ip, 0.0.0.0/0, crazy town
db86d211-0b09-4a8f-b222-a21a54ad2f9c, ip, 8.9.0.1, wild wood
db86d211-0b09-4a8f-b222-a21a54ad2f9c, ip, 0.0.0.0/0, wacky tabacky
611f8cf5-f6f2-4f3a-ad24-12245652a7bd, ip, 0.0.0.0/0, cuckoo cachoo

$ awk -F, '$3 !~/0\.0\.0\.0\/0/ && !seen[$1]++{print $1}' infile
64fe12c7-b50c-4f63-b292-99f4ed74e5aa
db86d211-0b09-4a8f-b222-a21a54ad2f9c

答案 1 :(得分:1)

Awk 解决方案:

awk -F',[[:space:]]*' '$3 !~ /^(0\.){3}0\/0/{ guids[$1] }
                       END{ for(k in guids) print k }' testfile.txt

输出:

db86d211-0b09-4a8f-b222-a21a54ad2f9c
64fe12c7-b50c-4f63-b292-99f4ed74e5aa

答案 2 :(得分:0)

听起来可以通过三步管道完成:

  1. 过滤掉第3列为0.0.0.0/0的行:grep -v '^[^,]*,[^,]*, *0\.0\.0\.0/0,'
  2. 选择第1列:cut -d, -f1
  3. 仅打印唯一元素:sort -u(或者,如果所有重复项都相邻,uniq
  4. grep -v '^[^,]*,[^,]*, *0\.0\.0\.0/0,' | cut -d, -f1 | sort -u
    

答案 3 :(得分:0)

添加另一个可能的解决方案,与其他提议的awk解决方案类似(但更丑陋,使用多个命令)。如果我正确理解了这个问题,你的条件#2已被#1考虑在内。无论如何,以下awk+sort为我工作:

awk -F, '$3!~/^ 0\.0\.0\.0\/0/ {print $1}' file.csv | sort -u

使用-u上的sort(唯一)标记,您将排除重复项。并非完全万无一失,但在这种情况下有效。

希望它有所帮助!

答案 4 :(得分:0)

关注awk也可以帮助您。

awk -F', +' '$3 ~ /0\.0\.0\.0\/0/{next} !a[$1]++{print $1}'   Input_file

输出如下。

64fe12c7-b50c-4f63-b292-99f4ed74e5aa
db86d211-0b09-4a8f-b222-a21a54ad2f9c