Bash

使用來自另一個文件的值更改文件 - Bash 腳本

  • December 10, 2019

我正在嘗試編寫一個腳本,該腳本將兩個文件作為參數並使用 .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">

  1. 您不需要將 CSV 讀入變數,您可以直接在 CSV 上循環:
cat data.csv | while IFS=, read id colour; do # something with $id and $colour
  1. var=$(echo text)有點多餘——你應該直接使用var="text"
  2. 我不確定您所說的結構是什麼意思[ "grep -E..." ],但這基本上是測試測試中的字元串是否不為空,這不是因為您只是在其中放入了一些文本。

在編寫 bash 腳本時,最好從命令行 (*) 依次測試每個表達式並查看它的行為是否符合您的預期 - 這樣可以消除很多意外。編寫一個完整的腳本然後執行它,沒有太多如何編寫好腳本的經驗,可能是一個很好的方法來射擊自己。我有多年編寫 bash 腳本的經驗,在將事情寫到腳本之前,我仍然嘗試在命令行上失敗了很多。當您執行腳本時,執行它-x以啟用命令跟踪將非常有幫助。

我猜您無法使替換工作的主要原因是 SVG 文件使用雙引號 ( ") 作為 ID 屬性,而不是像sed表達式中那樣使用單引號。

在 shell 腳本中構造sed表達式時,處理所有轉義通常很煩人。如果可能的話,我通常喜歡完全sed不引用表達式,這就是為什麼我經常使用不是斜杠的正則表達式分隔符的原因之一(我們接下來會看到)。您需要將idand的值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)中的情況。

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