【问题标题】:basic shell programming基本的shell编程
【发布时间】:2012-04-26 21:58:39
【问题描述】:

对于 shell 程序员来说,这可能是一个非常基本的问题。 但是假设我有一个文本文件 A 和 B B 是 A 的子集。

我想创建一个包含 (A-B) 数据的文本文件 C。

所以省略所有常见的行。

文件中的行是数字数据:like

id , some aspect, other aspec.

谢谢。

【问题讨论】:

  • 无论哪种方式,您都没有提到您的数据是否可以包含重复行。如果可以,请注意当A 中存在不匹配的重复行时,Tim Pote 的sort+uniq 方法不起作用awkcomm 方法确实适用于 A 中的重复项。

标签: bash shell awk


【解决方案1】:

使用sortuniq

sort a b | uniq -u

如果你想要A和B之间的线相同,你可以使用uniq -d

sort a b | uniq -d

这当然假设 A 和 B 中的数据完全相同相同。数据集中不能有任何丢失的空格或制表符。如果有,您必须先使用sedtrawk 清理数据。

编辑

作为彼得。 O 指出,如果文件a 中恰好有完全相同的重复项,这将失败。如果这是一个问题,您可以这样做来解决它:

sort <(sort -u a) b | uniq -u

【讨论】:

  • 一个非常幼稚的问题。如何将其保存在文件“c”中??
  • 您需要使用&gt; 重定向输出。所以命令将是:sort a b | uniq -u &gt; c
【解决方案2】:

有一个名为 comm 的实用程序仅用于此目的:

comm -23 A B > C

-2 表示“拒绝文件 B 独有的行”(你说没有),-3 表示“拒绝两个文件共有的行”。

@BartonChittenden 提出了一个很好的观点:

comm -23 <(sort A) <(sort B) > C

【讨论】:

  • 请注意,这两个文件都必须排序。
  • +1 向我展示了comm,这是我从未听说过的。 +10 向我展示了我从未听说过的 &lt;(command)
  • 这就是所谓的“进程替换”,让您可以将命令的输出视为文件。请参阅手册页。
【解决方案3】:

使用awk 的一种方式。重定向以将内容保存在任何文件中,而不是 STDOUT

awk 'FNR == NR { data[ $0 ] = 1; next } FNR < NR { if ( $0 in data ) { next } print $0 }' fileB fileA

UPDATED 使用更高效的命令。感谢 Peter.O

awk 'FNR==NR{data[$0]; next}; $0 in data{next}; 1' fileB fileA

【讨论】:

  • 只是几点让它更简洁(更快):1)您不需要为数组分配值;只是指它创建索引部分。 2) 不需要第二次 FNR 测试,因为前面的 next 可以满足此要求。 3) if 测试是多余的,因为$0 in data 本身就是一个测试。 4) 任何非零值都会导致$0 打印,因此print $0 可以是“布尔值”:awk 'FNR==NR{data[$0]; next}; $0 in data{next}; 1' fileB fileA
  • @Peter.O:谢谢你的建议。我将您的命令添加到答案中。
  • 您也不需要那些空语句(尾随分号),而不是在数据中测试 $0 并执行下一步,然后再进行隐式打印,您可以否定测试,并且你不需要下一个(除非 fileB 很大并且效率是一个问题)所以你可以把它写成awk 'FNR==NR{data[$0]} !($0 in data}' fileB fileA
【解决方案4】:
awk 'FNR==NR{a[$0];next}(!($0 in a))' B A

【讨论】:

    猜你喜欢
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多