Linux

從文件 2 中刪除文件 1 中的行

  • January 6, 2018

我確實有一個文本包含我想從我的原始文本中刪除的行。

例如

原文

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

文本包括要刪除的行

12,12
99999999999999999,19,1999,199

預期產出

11
111111111111111111,111111111,11

那麼這種情況的最佳解決方案是什麼?

這是一個單行使用者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

grepcomm命令也是如此:

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

我使用這個 awk one-liner 實現了上述結果

$ 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

引用自:https://unix.stackexchange.com/questions/408644