Linux
從文件 2 中刪除文件 1 中的行
我確實有一個文本包含我想從我的原始文本中刪除的行。
例如
原文
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
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
我使用這個 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