使用來自另一個文件的值更改文件 - Bash 腳本
我正在嘗試編寫一個腳本,該腳本將兩個文件作為參數並使用 .csv 文件中的值更改 .svg 文件。CSV 文件由具有兩個值的行組成;身份證,顏色。我需要在 svg 文件中找到 id 並將顏色添加到 id 匹配的行我不知道我的問題是否是 sed 部分,因為當在更改中引入變數時它會變得複雜,或者腳本基本上是有缺陷。
id=($(cut -f1 -d, $2)) colour=($(cut -f2 -d, $2)) file=$1 name=$(basename -s .svg $1) name1=$(echo "$name""1") cat $2 | while IFS=, read id colour; do sed -i "s/id=\"'"$id"'\"/id=\"'"$id"'\" style=\"fill:\"'"$colour"'\";\"/" "$1" done
當我使用它
sed -i 's/id="ca"/id="ca" style="fill:red;"/' data.svg
時,這會更改文件,但是當我將“ca”更改為“ $ id" or ‘" $ id"’,它不起作用。我也試過這個:
cat $2 | while IFS=, read id colour; do sed -i 's/id='"$id"'/id='"$id"' style="fill:red;"/' "$1" done
我得到的結果是這樣
<g id= style="fill:red;""hi">
的:預期的結果是這樣的:
<g id="hi" style="fill:red;">
當我像這樣將 $color 放入 sed 時
sed -i 's/id='"$id"'/id='"$id"' style="fill:'"$colour"';"/' "$1"
,我得到了:<g id= style="fill:;""hi">
- 您不需要將 CSV 讀入變數,您可以直接在 CSV 上循環:
cat data.csv | while IFS=, read id colour; do # something with $id and $colour
- 做
var=$(echo text)
有點多餘——你應該直接使用var="text"
。- 我不確定您所說的結構是什麼意思
[ "grep -E..." ]
,但這基本上是測試測試中的字元串是否不為空,這不是因為您只是在其中放入了一些文本。在編寫 bash 腳本時,最好從命令行 (*) 依次測試每個表達式並查看它的行為是否符合您的預期 - 這樣可以消除很多意外。編寫一個完整的腳本然後執行它,沒有太多如何編寫好腳本的經驗,可能是一個很好的方法來射擊自己。我有多年編寫 bash 腳本的經驗,在將事情寫到腳本之前,我仍然嘗試在命令行上失敗了很多。當您執行腳本時,執行它
-x
以啟用命令跟踪將非常有幫助。我猜您無法使替換工作的主要原因是 SVG 文件使用雙引號 (
"
) 作為 ID 屬性,而不是像sed
表達式中那樣使用單引號。在 shell 腳本中構造
sed
表達式時,處理所有轉義通常很煩人。如果可能的話,我通常喜歡完全sed
不引用表達式,這就是為什麼我經常使用不是斜杠的正則表達式分隔符的原因之一(我們接下來會看到)。您需要將id
and的值colour
放入sed
表達式中,同時正確辨識 SVG 屬性的引用。可能有效的一件事是:sed -i "s,id=\"$id\",id=\"$id\" style=\"fill:$colour;\"," "$1"
在這裡,我們只是在表達式周圍使用了雙引號——這允許我們嵌入變數——並且只是將雙引號轉義以匹配以防止它們終止 shell 字元串。
另一種選擇是由
sed
具有不同引用規則的多個字元串組成表達式:sed -i 's,id="'"$id"'",id="'"$id"'" style="fill:'"$colour"';",' "$1"
在這裡,我們將所有靜態文本放在單引號中,然後終止單引號並打開一個雙引號字元串來解析變數。這是可行的,因為單引號字元串和雙引號字元串之間沒有空格,並且只要沒有空格,Bash 就會將所有這些作為單個參數傳遞給
sed
. 但顯然這有點令人困惑,所以我更喜歡第一種風格。我們可以做的另一件事是使用
sed
擷取組不要id="$id"
多次鍵入:sed -i "s,\(id=\"$id\"\),\1 style=\"fill:$colour;\"," "$1"
\(
並擷取匹配的\)
內容,並將\1
其放回替換的字元串中。*) 如果您已經在 MS-Windows 中編寫過腳本,您可能會意識到命令行(無論是 CMD 還是 powershell)的行為與在腳本中執行相同的命令的行為不同,通常以不明顯的方式。這不是Unix 腳本外殼(例如 Bash)中的情況。