如何使用linux cmd基于列仅获取uniq行?

Raj*_*aju 2 text-processing

这是我的数据集:

col1,col2,col3
a,b,c
a,d,f
d,u,v
f,g,h
d,u,g
x,t,k
Run Code Online (Sandbox Code Playgroud)

预期输出:

f,g,h
x,t,k
Run Code Online (Sandbox Code Playgroud)

选择标准:

如果某件事多次发生col1,则所有关联的行都将被删除。

我可以使用 Linuxsortuniq其他方式解决这个问题吗?

Adm*_*Bee 9

这是一种“非缓冲” (1)两遍方法awk(仅适用于常规文件)。

awk -F',' 'NR==FNR{cnt[$1]++;next} FNR>1&&cnt[$1]==1' input.csv input.csv 
Run Code Online (Sandbox Code Playgroud)

这将处理该文件两次,因此在命令行上将其作为参数声明两次。

  • 该参数-F','将字段分隔符设置为,
  • 在第一遍中,当NR全局行计数器 等于每个FNR文件行计数器时,我们记录在数组中遇到第 1 列中的每个值的频率cnt(将该值作为“数组索引”),但立即跳到下一行处理。
  • 在第二遍中,我们检查第一列当前值的出现计数器是否恰好为 1,并且文件中的行号是否大于 1(以跳过标题)。仅当这是 true 时才会打印当前行。这利用了awk规则块之外的表达式的语法,该表达式的计算结果是true指示awk打印当前行。

(1)作为对评论的回应,我将非缓冲放在引号中,因为由于该解决方案会将文件中的一些数据临时存储在 RAM 中,因此它确实会占用 RAM。然而,除了RAM 中的任何其他滚动保持数据之外,它不会逐字存储文件内容(认为在实际意义上是“缓冲”)。

  • @EdMorton是的,我有点怀疑这是一个偶然的“路过投票者”,他们不愿意提供建设性的批评(我看到你的答案也收到了其中之一......)。但我还没有放弃希望,有一天他们中的一个可能会真正做出反应;) (4认同)
  • LGTM,我之前投了 FWIW 票。总有人无缘无故地跑来投反对票。 (2认同)
  • 我有一个特别的粉丝向模组抱怨我对他们的答案提供了建设性的反馈(就像我对每个人所做的那样,如果我认为这有用的话),因为他们认为我在挑剔他们,我很确定那是他们对我的大部分答案都投了反对票,如果他们向过去也试图帮助他们的其他人提供同样的礼貌,我不会感到惊讶。如果我可以花 SE 点,我会担心的:-)。 (2认同)

Gar*_*aro 6

假设该文件是/tmp/data您可以使用 perl 单行代码来完成的:

perl -e 'while(<STDIN>) { /(^\S+?),/; $show->{$1}=$_; $count->{$1}++;}; foreach(keys %$show) {print $show->{$_} if($count->{$_} == 1);}' < /tmp/data

或者更具可读性...:

while(<STDIN>) { #loop through all lines in the input and put the lines in "$_"
  /(^\S+?),/; #Everything before the first "," now ends up in "$1"
  $show->{$1} = $_; #a hash will be created with as keys the "$1" and as values the "$_"
  $count->{$1}++; #In the hash $count the number of occurrences will be increased everytime the same $1 appears
}
foreach(keys %$show) { #loop trough all lines
  print $show->{$_} if($count->{$_} == 1); #only print them if they occur once
}
Run Code Online (Sandbox Code Playgroud)


Arc*_*mar 5

awk唯一的解决方案

  1. 不遵守秩序

    awk -F, 'NR>1 { count[$1]++ ; line[$1]=$0 ;} 
       END { for ( c in count) if (count[c] ==1) print line[c]}' data
    
    Run Code Online (Sandbox Code Playgroud)
  2. 维持秩序

    awk -F, 'NR>1 { row[a]=$0; col[a]=$1; count[$1]++; ++a; } 
       END { for (i=0; i<a; ++i) if (count[col[i]]==1) print row[i]; }' data
    
    Run Code Online (Sandbox Code Playgroud)

在哪里

  • -F,告诉 awk 用作,分隔符

  • NR>1 第一行之后

  • count[$1]++计算第一列的元素

  • line[$1]=$0 商店线

  • END文件结束后

  • for ( c in count)循环遍历元素

  • if (count[c] ==1)如果只有一个

  • print line[c]打印行

  • acol[]用于存储顺序保留变体中的行顺序。

这可以单行,为了可读性我折叠起来

  • @schrodigerscatcuriosity 它不会颠倒顺序,它会根据“in”运算符以“随机”顺序打印行,请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Scanning-数组。因此,您可以获得输入顺序,或者可以反转输入顺序,或者可以获得任何其他输出顺序。 (2认同)