2012-04-26 68 views
9

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

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

因此省略所有的通用线。

在文件中的线是数字数据:像

id , some aspect, other aspec. 

感谢。

+0

您还没有提到,无论哪种方式,你的数据是否可以包含重复行。如果可以的话,那么请注意,当“A”中存在不匹配的重复行时,Tim Pote的'sort' +'uniq'方法**不起作用。 'awk'和'comm'方法可以在'A'中重复使用。 – 2012-04-27 05:50:56

回答

12

使用sortuniq

sort a b | uniq -u 

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

sort a b | uniq -d 

在假定的是,在A的数据和B是,正好是一样。数据集中不能有任何丢失空格或制表符。如果有,则必须首先使用sed,trawk清理数据。

编辑

正如彼得。 O指出,如果碰巧在文件a中出现重复,这将失败。使用awk

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

一个非常天真的问题。我如何将它保存在文件“C”? – Fraz 2012-04-26 22:05:42

+1

您需要使用'>'重定向输出。所以命令将会是:'sort a b | uniq -u> c' – 2012-04-26 22:06:27

+1

'sort a b | uniq -u> c' – dpp 2012-04-26 22:07:02

4

方式一:如果这是一个问题,你可以这样做修复它。重定向以保存任何文件中的内容而不是STDOUT

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

修订具有更有效的命令。由于Peter.O

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

只需要几点让它变得更加consise(和更快):1)你不需要为数组赋值;只是指它创建索引部分。 2)第二次FNR测试是不需要的,因为前面的'next'迎合了这一点。 3)“if”测试是多余的,因为数据中的“$ 0”本身就是一个测试。 4)任何非零值都会导致$ 0被打印,所以'print $ 0'可以是一个“布尔值”:'awk'FNR == NR {data [$ 0];下一个};数据{next} $ 0; 1'fileB fileA' – 2012-04-27 04:25:37

+0

@ Peter.O:谢谢你的建议。我把你的命令加到答案上。 – Birei 2012-04-27 08:01:35

+0

您也不需要那些空语句(尾随分号),而不是在数据中测试$ 0并在下一步做测试,然后再隐式打印,您可以忽略测试,并且不需要第一个下一步(除非fileB是巨大的,效率是一个问题),所以你可以把它写成'awk'FNR == NR {data [$ 0]}!($ 0 in data)'fileB fileA'。 – 2012-11-16 05:31:57

7

有一个名为comm实用程序的二手只是这样的:

comm -23 A B > C 

其中-2手段“拒绝独特的文件B线”(你说有AREN 't any),-3表示“拒绝这两个文件共有的行”。

@BartonChittenden使得一个好点:

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

注意这两个文件都必须是 – 2012-04-27 02:07:27

+0

+1给我展示'comm',这是我从来没有听说过的。+10给我展示'<(command)'我从来没有听说过。 – 2012-04-27 13:18:53

+1

这就是所谓的“过程替代”,可以让你对待输出一个命令,就好像它是一个文件一样,见手册页。 – 2012-04-27 15:35:27

2
awk 'FNR==NR{a[$0];next}(!($0 in a))' B A