我确实有一个文本包含我想从原始文本中删除的行。
作为例子
原文
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