我有一个很大的文件a(由电子邮件组成),每封邮件一行。我还有另一个文件B,其中包含另一组邮件。
我将使用哪个命令从文件A中删除文件B中出现的所有地址。
因此,如果文件A包含:
A
B
C
文件B包含:
B
D
E
那么文件A应该剩下:
A
C
现在我知道这是一个可能经常被问到的问题,但我只在网上找到一个命令,它给我一个错误的分隔符。
任何帮助都将不胜感激!肯定有人会想出一个聪明的俏皮话,但我不是shell专家。
我有一个很大的文件a(由电子邮件组成),每封邮件一行。我还有另一个文件B,其中包含另一组邮件。
我将使用哪个命令从文件A中删除文件B中出现的所有地址。
因此,如果文件A包含:
A
B
C
文件B包含:
B
D
E
那么文件A应该剩下:
A
C
现在我知道这是一个可能经常被问到的问题,但我只在网上找到一个命令,它给我一个错误的分隔符。
任何帮助都将不胜感激!肯定有人会想出一个聪明的俏皮话,但我不是shell专家。
当前回答
您可以这样做,除非您的文件已排序
diff file-a file-b --new-line-format="" --old-line-format="%L" --unchanged-line-format="" > file-a
——new-line-format用于文件b中但不在文件a中的行 ——老. .是在文件a中但不在文件b中的行吗 ——不变. .是同时存在于两者中的行。 %L使行被精确地打印出来。
man diff
欲知详情
其他回答
你可以使用- diff fileA fileB | grep "^>" | cut -c3- > fileA
这也适用于没有排序的文件。
你可以使用Python:
python -c '
lines_to_remove = set()
with open("file B", "r") as f:
for line in f.readlines():
lines_to_remove.add(line.strip())
with open("file A", "r") as f:
for line in [line.strip() for line in f.readlines()]:
if line not in lines_to_remove:
print(line)
'
grep -Fvxf <删除行> <所有行>
适用于未排序的文件(与comm不同) 维护秩序 是POSIX
例子:
cat <<EOF > A
b
1
a
0
01
b
1
EOF
cat <<EOF > B
0
1
EOF
grep -Fvxf B A
输出:
b
a
01
b
解释:
-F:使用文字字符串而不是默认的BRE -x:只考虑匹配整行的匹配 -v:打印不匹配 -f file:从给定文件中获取模式
这种方法在预排序文件上比其他方法慢,因为它更通用。如果速度也很重要,请参阅:查找一个文件中不在另一个文件中的行的快速方法?
下面是一个用于内联操作的快速bash自动化:
remove-lines() (
remove_lines="$1"
all_lines="$2"
tmp_file="$(mktemp)"
grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
mv "$tmp_file" "$all_lines"
)
GitHub上游。
用法:
remove-lines lines-to-remove remove-from-this-file
参见:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another
要删除两个文件之间的公共行,可以使用grep、comm或join命令。
Grep只适用于小文件。使用-v和-f。
grep -vf file2 file1
这将显示file1中与file2中任何行不匹配的行。
Comm是一个实用命令,用于按词法排序的文件。它 以两个文件作为输入,并产生三个文本列作为输出: 只在第一个文件中的行;只在第二个文件中的行;和线 在两个文件中。可以使用-1、-2来抑制任何列的打印 或相应的-3选项。
comm -1 -3 file2 file1
这将显示file1中与file2中任何行不匹配的行。
最后是join,这是一个执行相等操作的实用命令 在指定文件上连接。它的-v选项也允许删除 两个文件之间的公共行。
join -v1 -v2 file1 file2
对于非常大的文件,@karakfa的答案的改进可能会明显更快。与这个答案一样,两个文件都不需要排序,但是由于awk的关联数组,速度得到了保证。只有查找文件保存在内存中。
这个公式还允许在比较中只使用输入文件中的一个特定字段($N)。
# Print lines in the input unless the value in column $N
# appears in a lookup file, $LOOKUP;
# if $N is 0, then the entire line is used for comparison.
awk -v N=$N -v lookup="$LOOKUP" '
BEGIN { while ( getline < lookup ) { dictionary[$0]=$0 } }
!($N in dictionary) {print}'
(这种方法的另一个优点是很容易修改比较标准,例如,修剪开头和结尾的空白。)