Shell-Script

如果文件中不存在這些行,如何將多行附加到文件中?

  • October 1, 2020

如果文件中不存在這些行,如何將多行附加到文件中?

例如,要添加多個全域別名,/etc/bash.bashrc我使用heredocument

cat <<-"BASHRC" >> /etc/bash.bashrc
   alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
   alias brc="nano /etc/bash.bashrc"
BASHRC

我被批評說這個操作不包括檢查行是否已經存在的方法,如果錯誤地重新執行 heredocument,我可能會導致冗餘以及沖突。

用於將文件中的行添加newdatadatafile. 更改newdata為 here-doc 應該很簡單。這實際上不是很有效,因為它需要grep每個(新)輸入行:

target=datafile
while IFS= read -r line ; do
   if ! grep -Fqxe "$line" "$target" ; then
       printf "%s\n" "$line" >> "$target"
   fi
done < newdata 

對於每一行,我們使用grep它來查看它是否已經存在於目標文件中,-F用於固定字元串匹配(無正則表達式),-x用於全行匹配,並-q抑制匹配行的輸出。grep如果沒有找到匹配的行,則返回虛假錯誤程式碼,因此如果否定結果為真,則附加到目標文件。


更有效地,在awk. 這依賴於awk能夠將任意行作為數組的鍵來處理。

$ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata 

第一部分FNR == NR { lines[$0] = 1; next }將第一個輸入文件的所有行作為鍵載入到(關聯)數組lines中。第二部分! ($0 in lines) {print}在以下輸入行上執行,如果該行不在數組中,則列印該行,即“新”行。

結果輸出僅包含新行,因此需要將其附加到原始文件中,例如sponge

$ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata | sponge -a datafile

或者我們可以awk將這些行附加到最後一行,它只需要將文件名傳遞給awk

$ target=datafile 
$ awk -vtarget="$target" 'FNR == NR { lines[$0] = 1; next } 
                       ! ($0 in lines) {print >> target}' "$target" newdata

要將 here-doc 與 一起使用,除了設置重定向之外awk,我們還需要將(stdin) 添加為顯式源文件,因此-``awk ... "$target" - <<EOF

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