从文件 2 中删除文件 1 中的行

从文件 2 中删除文件 1 中的行

我确实有一个文本包含我想从原始文本中删除的行。

作为例子

原文

11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199

文本包括要删除的行

12,12
99999999999999999,19,1999,199

预期输出

11
111111111111111111,111111111,11

那么对于这种情况最好的解决方案是什么?

答案1

我使用 awk 单行代码实现了上述结果

$ cat file1
11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199
$ cat file2
12,12
99999999999999999,19,1999,199

以下命令从 file1 中删除 file2 的内容

awk 'NR==FNR {a[$1];next}!($1 in a ) {print $1}' file2 file1

输出:

11
111111111111111111,111111111,11

答案2

这是一位单行用户grep

grep -Fxv -f file1.txt file2.txt

此命令按照它们出现的顺序输出file1.txt不在其中的行。file2.txt

如果您不关心保留顺序,您还可以使用以下comm命令:

comm -23 <(sort file1.txt) <(sort file2.txt)

此命令按排序顺序输出file1.txt不在 - 中的行。file2.txt

您还可以使用 while 循环迭代第一个文件的行(例如file1.txt),使用 对照第二个文件(例如file2.txt)检查每一行grep,如果未找到则打印该行。这将产生包含file1.txt已删除的行的文本的效果file1.txt。它可能看起来像这样:

while read line; do
    if ! grep -qF -- "${line}" file2.txt; then
        echo "${line}";
    fi;
done < file1.txt

如果要将结果写入文件,可以使用输出重定向,例如:

while read line; do
    if ! grep -qF -- "${line}" file2.txt; then
        echo "${line}";
    fi;
done < file1.txt > output.txt

grep和命令也是如此comm

grep -Fxv -f file1.txt file2.txt > output.txt
comm -23 <(sort file1.txt) <(sort file2.txt) > output.txt

笔记:您无法将输出重定向回file1.txt.由于输出重定向的实现方式,这最终只会删除file1.txt.有关此问题的进一步讨论,请参阅以下帖子:

如果你想替换原始文件,你可以用输出文件覆盖它,即:

mv output.txt file1.txt

您也可以将其变成脚本。这是使用 while 循环的脚本:

#!/usr/bin/env bash
# removelines.sh

# Set filenames
INPUTFILE="$1"
FILTERFILE="$2"
OUTPUTFILE="$(mktemp)"

# Write the lines from INPUTFILE to OUTPUTFILE
# minus the lines from FILTERFILE
while read line; do
    if ! grep -qF -- "${line}" "${FILTERFILE}"; then
        echo "${line}";
    fi;
done < "${INPUTFILE}" > "${OUTPUTFILE}"

# Replace INPUTFILE with OUTPUTFILE
mv "${OUTPUTFILE}" "${INPUTFILE}"

这是使用相同的脚本comm

#!/usr/bin/env bash
# removelines.sh

# Set filenames
INPUTFILE="$1"
FILTERFILE="$2"
OUTPUTFILE="$(mktemp)"

# Write the lines from INPUTFILE to OUTPUTFILE
# minus the lines from FILTERFILE
comm -23 <(sort "${INPUTFILE}") <(sort "${FILTERFILE}") > "${OUTPUTFILE}"

# Replace INPUTFILE with OUTPUTFILE
mv "${OUTPUTFILE}"

请注意,我使用该mktemp函数为输出文件生成随机文件名。

脚本实际运行时的样子如下:

user@host:~$ cat <<HEREDOC > file1.txt
11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199
HEREDOC

user@host:~$ cat <<HEREDOC > file2.txt
12,12
99999999999999999,19,1999,199
HEREDOC

user@host:~$ bash removelines.sh file1.txt file2.txt

user@host:~$ cat file1.txt
11
111111111111111111,111111111,11

相关内容