2012-10-19 85 views
1

我一直在修改名爲「.backup.conf」的配置文件的shell腳本時遇到了一些問題。Bash - 使用sed更改配置文件

配置文件看起來是這樣的:

inputdirs=(/etc /etc/apm /usr/local) 
outputdir="test_outputdir" 
backupmethod="test_outputmethod" 
loglocation="test_loglocation"` 

我的腳本需要更改配置文件中的變量之一,我已經與過去的3個變量沒有煩惱。

如果我想更改變量「inputdirs」/ etc/to/etc/perl,應該使用什麼表達式?

如果我用append使用echo,它只會將它附加到文件的末尾。

我試過在以下格式中使用sed: sed -i 's/${inputdirs[$((izbor-1))]}/$novi/g' .backup.conf其中「izbor」是我想從inputdirs更改的變量,「novi」是新路徑(例如/ etc/perl)。

所以,用下面的配置文件,並用變量$izbor=1$novi=/etc/perl我應該第一個變量inputdirs=/etc更改爲/etc/perl 和可變inputdirs應該終於看起來像inputdirs=(/etc/perl /etc/apm /usr/local)

謝謝您的幫助!

+0

Sed是一個流編輯器。你正在做一個正則表達式搜索/替換字符串......但試圖在數組上操作? – Madbreaks

+0

如果與/ g一起使用,不應該在整個文件中搜索條件? – Juraj

+0

這不是'g'做的,'g'是「全部取代」。但不管 - 您的搜索表達式是無效的。 http://www.grymoire.com/Unix/Sed.html#uh-1 – Madbreaks

回答

2

你可以試試這個:

enovi="$(printf '%s\n' "$novi" | sed -e 's/[\\&/]/\\&/g')" 
izbor1="$(expr "$izbor" - 1)" 
sed -rie "s/([(]([^ ]*){$izbor1})[^)]*/\\1$enovi/" config.txt 

命令摘要:

  1. 第一行生成一個變量$enovi擁有的$novi轉義內容。基本上,下列字符被轉義:&,\/。因此/etc/perl變成\/etc\/perl
  2. 我們創建了一個遞減$izbor的新變量。
  3. 這是實際的替代表達式。我將分開解釋它:
    1. 首先我們匹配括號字符[(]
    2. 我們現在將搜索一系列非空格後跟一個空格([^ ]*)。
    3. 此搜索(在括號內標識分組)被重複$izbor1倍({$izbor1}
    4. 先前表達式被分組爲一個外括號組以被捕獲到一個輔助變量\1
    5. 我們現在匹配我們想要替換的詞。它由一系列不是空格的字符組成,並且不是一個右括號(這是爲了處理最後一個單詞的情況)
    6. 替換是由捕獲的值\1形成的,後面是我們的新字符串。

希望這有助於=)

+0

我得到了sed:-e表達式#1,字符30:未知選項到's' – Juraj

+0

是的,我忘了'$ novi'是一個路徑,所以它會混淆sed 。解決方法是在使用它之前先將字符串轉義出來,所以我更新了文章以創建一個新變量'$ enovi',其中包含'$ novi'的轉義版本。 –

+0

這一個似乎工作,但conf文件中的變量現在看起來像這樣:'inputdirs =(/ etc/apm/usr/local)',但應該看起來像'inputdirs =(*我輸入的值*/etc/apm/usr/local)' – Juraj

1

如果你要使用$ izbor作爲索引,它可能會想成爲一個標誌s///。假設你的輸入相匹配^inputdirs=((無空格),你也許可以矇混過關:

sed -i '/^inputdirs=(/{ 
    s/(/( /; s/)/)/; # Insert spaces inside parentheses 
    [email protected] [^ ][^ ]* @ '"[email protected]$izbor"'; 
    s/(/(/; s/)/)/; } # Remove inserted spaces 
' .backup.conf 

前兩個表達式確保您有空白的括號內, 所以可能沒有必要,如果你的輸入已經有空白那裏。這是一個有點混淆以上,但基本上你正在做的更換是一樣的東西:

[email protected] [^ ][^ ]* @/etc/[email protected] 

其中2標誌告訴sed只替換本場比賽的第二次出現。這是非常脆弱的,因爲它不需要在inputdirs之前沒有空格,並且在parens裏面沒有空格,並且不能處理標籤,但它應該適合你。此外,有些sed允許[^ ][^ ]*寫入更簡單,如[^ ]+,但這不是通用的。

+0

謝謝你的詳細解釋,但是我在找'意想不到的EOF'時''' – Juraj

+0

我的錯誤 - 編輯'izbor'後缺少一個單引號 –

+0

測試過它,它的工作,但它增加了前面的空間,所以現在看起來像'inputdirs =(/ etc/perl/etc/apm/usr/local)' – Juraj