在bash
腳本中,如何sed
寫入檔案名稱儲存在 bash 變數中的檔案?輸出重定向不起作用,因為我想就地編輯一個文件,將與正規表示式匹配的行拉到另一個文件中,然後在第一個文件中刪除它們。
就像是:
sed -i '/^my regex here$/{;w file2;d;}' file1
……但是file1
和file2
兩者實際上都在哪裡變數那抓住文件名。 (例如file2=$(mktemp)
。)
所以我真正想要的是文件名的變數擴展,但命令的其餘部分沒有擴展sed
,並將整個內容作為傳遞給sed
命令的單一參數。
無論出於何種原因,以下方法都不起作用:
sed -i '/my regex here/{;w '"$file2"';d;}' $file1
它說“不匹配{”,我不明白為什麼。
我有什麼辦法可以做到這一點嗎?
答案1
因為您使用的是單一表達式,所以(包括)sed
之後的所有內容都是w
}
解釋為工作文件姓名:
此參數
wfile
應終止編輯命令。
您可以看到,如果新增第二個命令}
,例如:
sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1
那麼符合的行將會my regex here
保存在名為whatever;d;}
wherewhatever
是$file1
擴充後的檔案中。
正確的語法是透過單獨的命令,或使用多個表達式:
sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2
或每行一個指令:
sed '/my regex here/{
w '"$file1"'
d
}
' $file2
答案2
我找到了答案堆疊溢位在“如何讓 sed 'w' 命令知道文件名在哪裡結束?”
正如 terdon 指出的那樣,問題不在於變量,但它也與大括號無關;嘗試一下sed '/^l/w testing;p'
,您會發現它不會拋出任何錯誤,而是將以 an 開頭的所有行寫入l
名為testing;p
.
問題實際上是檔案名稱後缺少換行符。
所以答案是在 sed 指令中使用內聯換行符:
sed -i '/my regex here/{;w '"$file2"'
d;}' $file1
或者,更簡潔的是,使用兩個單獨的-e
參數:
sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1
如果您不喜歡兩個相鄰的引號(您可能很容易忽略它們),只需將 write 命令放在它自己的參數中即可:
sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1
答案3
使用雙引號代替單引號來引用 sed 指令。並且不要忘記轉義合適的字元。
有關在 bash 中引用變數的更多信息,請參見這裡關聯