【问题标题】:Awk: find duplicates in 3rd field INCLUDING originalawk:在第三个字段中查找重复项,包括原始项
【发布时间】:2015-05-12 19:11:46
【问题描述】:

我想出了以下代码来在 passwd 文件中查找重复的 UID,但它不包括第一个实例(后来被复制的那个),我最终想要一个带有 UID = [ USER1, USER2 ] 的字典,但我是不知道如何在 Awk 中完成。

到目前为止我所拥有的:

awk -F':' '$1 !~ /^#/ &&  _[$3]++ {print}' /etc/passwd  

解释(据我所知),如果正则表达式匹配不以注释“#”开头的行,则根据当前行 UID 值增加一个数组,使该行变为非零/真值,从而打印它.

【问题讨论】:

  • 至少在扫描期间第一次看到它时,您无法区分将被复制的 UID 和不会复制的 UID。为此,您需要保存所有匹配的行并在最后打印出来。
  • 使用这种类型的 awk 语句最节省内存的方法是什么?
  • 我能想到的最好的办法是在处理过程中存储每个“第一”行,然后在 END 处循环,并打印每个计数大于 1 的“第一”行。
  • 不要使用名为 _ 的变量。您真的不能认为这样做会使您的代码以任何其他可能的方式更具可读性或更好。发布示例输入和预期输出,如果您希望最终输出看起来像 UID = [ USER1, USER2 ],那么显示 THAT,而不是像当前脚本那样产生一些不必要的中间形式。
  • @EdMorton 如果我没有提供一些“中间”版本的解决方案,其他人会抱怨我没有表现出任何努力来解决这个问题,这似乎在这个社区。很遗憾,我无法取悦所有人。

标签: dictionary awk associative-array


【解决方案1】:

这可能会帮助您做到这一点。首先,我们将数据保存在一个数组中,然后在 END{} 块中我们打印数组中所有重复的行(您也可以在执行时打印)。希望对你有帮助

awk -F":" '
    $1 !~ /^#/ && (counter[$3]>0) {a++;print "REPEATED|UID:"$3"|"$0"|"LastReaded[$3]; repeateds["a"a]=$0; repeateds["b"a]=LastReaded[$3]}
    $1 !~ /^#/ { counter[$3]++; LastReaded[$3]=$0} 
    END {for (i in repeateds)
         {
            print i"|"repeateds[i]
         }
    }
' /etc/passwd  

REPEATED|UID:229|pepito:*:229:229:pepito:/var/empty:/usr/bin/false|_avbdeviced:*:229:-2:Ethernet AVB Device Daemon:/var/empty:/usr/bin/false
a1|pepito:*:229:229:pepito:/var/empty:/usr/bin/false
b1|_avbdeviced:*:229:-2:Ethernet AVB Device Daemon:/var/empty:/usr/bin/false

【讨论】:

    猜你喜欢
    • 2012-03-22
    • 2013-09-30
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多