2011-08-23 57 views
1

這是我的問題,我寫了下面這行代碼來正確地格式化在目錄中遞歸找到的文件列表。SED壞代替錯誤

find * | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\(\)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/" 

第二步是將此命令的輸出寫入腳本。雖然上面的代碼具有預期的行爲,但是當我嘗試將其輸出存儲到變量時發生問題,我從行中的第一個sed命令得到了錯誤的替換錯誤。

#!/bin/bash 
nsisscript=myscript.sh 
FILES=* 
for f in $(find $FILES); do 
v=`echo $f | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\(\)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/"` 
sed -i.backup -e "s/\;Insert files here/$v\\n&/" $nsisscript 
done 

請你幫我理解兩種情況之間有什麼不同,以及爲什麼我得到這個錯誤?

在此先感謝!

+0

嗯......我想我自己找到了解決方案。在分隔符裏面,「$」被解釋爲某種原因,無論是單獨還是在它之前有一個反斜槓。解決方法是在每個「$」字符前加2個反斜槓。 v ='echo $ f | sed -e'/\(.*\..*\)/!d'| sed -e「s /^.*/\\$ {File} \\ $ {INST \ _FILES}&/」..... 我很樂意聽到爲什麼會出現這種情況, 。 – Patrick

+0

與您的問題本身無關,但似乎您不知道可以更改sed的分隔符,因此您不必跳過斜線。只要選擇另一個你不需要的字符,比如':':'sed's:pattern:substitution:',這將大大提高正則表達式在處理路徑時的可讀性 – carlpett

回答

0

嗯,我的猜測是,你在INST_FILES中下劃線的轉義很奇怪,因爲下劃線不是shell或sed中的特殊字符。當你面前「_」

我的2美分刪除「\」

+0

你說的錯誤消失是正確的。手動改變行爲並且輸出結果不是我想象的那樣,雙反斜槓解決方案似乎可以工作 – Patrick

0

解析反引號風格的命令替換裏面的錯誤消失是有點不可思議 - 它需要逃避的一個額外的水平(即反斜槓)以控制何時進行擴展。醜陋的解決方案:添加更多反斜槓。更好的解決方案:使用$()而不是反引號 - 它做同樣的事情,但沒有奇怪的解析和轉義問題。

順便說一句,你的腳本似乎有一些其他問題。首先,我不知道系統上的sed,但我熟悉的版本不會將替換中的\n解釋爲新行(我認爲您需要),而是將其作爲文字n字符。一種解決方案是在替換中包含一個字面換行符(在反斜槓前面)。

此外,循環會爲每個找到的文件執行,但對於名稱中沒有句點的文件,第一個sed命令會將其刪除,$v爲空,並且會向myscript.sh中添加空行。您應該將過濾sed調用放入for語句中,或者將其作爲篩選器添加到find命令中。

#!/bin/bash 
nsisscript=myscript.sh 
nl=$'\n' 
FILES=* 
for f in $(find $FILES -name "*.*"); do 
    v=$(echo $f | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\(\)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/") 
    sed -i.backup -e "s/\;Insert files here/$v\\$nl&/" $nsisscript 
done 
+0

嗨,謝謝你的回答,我喜歡$()技巧而不是後面的引號,我認爲這很麻煩。另一方面,我沒有任何與換行符有關的問題,每次在文件中輸入一行時,正確的後面跟着一個換行符,然後按照預期在下面插入文件。 – Patrick