我正在編寫腳本來處理文本文件。BASH - 判斷是否存在重複行(y/n)
我想要做的第一件事是檢查是否存在重複的條目,如果是,請詢問用戶是否要保留或刪除它們。
我知道如何顯示重複的行,如果它們存在,但我想要學習的只是對「存在重複嗎?」這個問題得到肯定/否定的答案。
看起來uniq
將返回0
要麼重複發現或沒有找到重複只要命令完成沒有問題。
我可以在if
-statement中輸入什麼命令來告訴我是否存在重複行?
我的文件很簡單,它只是單列中的值。
我正在編寫腳本來處理文本文件。BASH - 判斷是否存在重複行(y/n)
我想要做的第一件事是檢查是否存在重複的條目,如果是,請詢問用戶是否要保留或刪除它們。
我知道如何顯示重複的行,如果它們存在,但我想要學習的只是對「存在重複嗎?」這個問題得到肯定/否定的答案。
看起來uniq
將返回0
要麼重複發現或沒有找到重複只要命令完成沒有問題。
我可以在if
-statement中輸入什麼命令來告訴我是否存在重複行?
我的文件很簡單,它只是單列中的值。
您可以使用awk
與布爾||
運營商合併:
# Ask question if awk found a duplicate
awk 'a[$0]++{exit 1}' test.txt || (
echo -n "remove duplicates? [y/n] "
read answer
# Remove duplicates if answer was "y" . I'm using `[` the shorthand
# of the test command. Check `help [`
[ "$answer" == "y" ] && uniq test.txt > test.uniq.txt
)
的||
後,該塊將只能得到,如果awk命令返回1執行,這意味着它發現重複。
然而,一個基本的瞭解,我會還使用if
塊
awk 'a[$0]++{exit 1}' test.txt
# $? contains the return value of the last command
if [ $? != 0 ] ; then
echo -n "remove duplicates? [y/n] "
read answer
# check answer
if [ "$answer" == "y" ] ; then
uniq test.txt > test.uniq.txt
fi
fi
顯示一個例子。然而[]
是不只是括號像其他編程語言。 [
是test
bash內建命令的同義詞,]
是最後一個參數。您需要以瞭解閱讀help [
感謝您的幫助。我會嘗試一下你的代碼。 – DMS
快速bash的解決方案:
#!/bin/bash
INPUT_FILE=words
declare -A a
while read line ; do
[ "${a[$line]}" = 'nonempty' ] && duplicates=yes && break
a[$line]=nonempty
done < $INPUT_FILE
[ "$duplicates" = yes ] && echo -n "Keep duplicates? [Y/n]" && read keepDuplicates
removeDuplicates() {
sort -u $INPUT_FILE > $INPUT_FILE.tmp
mv $INPUT_FILE.tmp $INPUT_FILE
}
[ "$keepDuplicates" != "Y" ] && removeDuplicates
腳本從INPUT_FILE並存儲關聯數組a
爲重點,在每一行逐行地讀取並設置字符串作爲價值的nonempty
。在存儲該值之前,它首先檢查它是否已經存在 - 如果是這意味着它發現重複並且它設置duplicates
標誌,然後突破該週期。
後來它只檢查標誌是否設置並詢問用戶是否保留重複項。如果他們回答Y
以外的任何內容,則它會調用removeDuplicates
函數,該函數使用sort -u
刪除重複項。 ${a[$line]}
評估爲關鍵字$line
的關聯數組a
的值。 [ "$duplicates" = yes ]
是用於測試的bash內建語法。如果測試成功,則在&&
之後進行評估。
但請注意,awk解決方案可能會更快,所以如果您希望處理更大的文件,您可能需要使用它們。
謝謝jkbkot!你可以給我一個關於這個代碼如何工作的簡要說明嗎?我是菜鳥:) – DMS
@DMS沒問題,補充說明。順便說一句,upvoting是不夠的,謝謝;),也嘗試接受其中的一個答案,以保持網站的組織。快樂的編碼! –
我可能會使用awk
要做到這一點,但對於不同的緣故,這裏是一個簡短的管道完成同樣的事情:
$ { sort | uniq -d | grep . -qc; } < noduplicates.txt; echo $?
1
$ { sort | uniq -d | grep . -qc; } < duplicates.txt; echo $?
0
sort
+ uniq -d
確保只有重複的行(這不必相鄰)打印到stdout
和grep . -c
計算那些仿效wc -l
的行,如果它不匹配(即零計數)並且-q
只是使輸出保持靜默,那麼它不會產生有用的副作用,它會返回1
,打印行數,以便您可以在腳本中靜靜地使用它。
has_duplicates()
{
{
sort | uniq -d | grep . -qc
} < "$1"
}
if has_duplicates myfile.txt; then
echo "myfile.txt has duplicate lines"
else
echo "myfile.txt has no duplicate lines"
fi
如果你不反對使用Vim進行人工過濾的文本文件,我建議在http://stackoverflow.com/questions/1268032的'HighlightRepeats'方法。我經常用它來過濾重複的文件/文件夾,然後在過濾的文件上應用shell命令。 –
@ F.X感謝您的回覆。我想用腳本中的一些行來完成此操作。 – DMS