2011-07-19 183 views
1

工作,我有一個shell腳本,如下所示:SED命令不會在shell腳本

#!/bin/bash 
for file in $1/*.html; do 
    echo "Working on $file ..." 

    # delete headers in html files. 
    sed -n '1,9d' $file 

    # delete the last 4 lines of the file. 
    sed -n -e :a -e '1,4!{P;N;D;};N;ba' 

    # ant runs regex task on all apt files 
    ant -Dtarget.file=$file 

    # all .html are changed to .md 
    mv $file `echo $file | sed 's/\(.*\.\)html/\1md/'` ; 

done 

但腳本掛在第一sed命令,我必須強制退出。我想知道我設置的方式有什麼問題嗎?

如果我刪除前兩個sed命令,我可以運行腳本的其他部分,包括最後一個包含sed命令的部分。

+1

'mv'讓我感到畏懼,因爲沒有用的昂貴的fork到另一個'sed'。如果您只想替換存儲在變量中的文件名中的擴展名,請使用'mv $ file $ {file%.html} .md'。 – Jens

回答

0

你正在運行什麼命令?如果沒有匹配文件glob,那麼它將物理插入未展開的字符串。

例如,試試這個:

$ for i in foo/*.bar; do echo $i; done 
foo/*.bar 

所以你的sed腳本被轟炸,因爲它正在接收不存在的文件名,這意味着它將如果沒有指定文件參數的行爲(即標準輸入)。

+0

如果文件不存在,我很肯定'sed'不會像你指定沒有文件那樣工作,而是它會怨聲載道:-) – paxdiablo

4

我想你會發現它掛在第二個sed,你沒有提供一個文件名來處理。換句話說,它將採用終端的標準輸入。

由於-n阻止默認打印模式空間,所以不會從第一個sed獲得輸出。如果您嘗試更改實際的文件而不是將更改輸出到標準輸出,則需要-i就地編輯器。

如果您不能使用就地選項,你必須做一些事情,如:

sed -n '1,9d' ${file} >${file}.tmp0 
sed -n -e :a -e '1,4!{P;N;D;};N;ba' ${file}.tmp0 >${file} 
rm -f ${file}.tmp0 

這將使用臨時文件製作除了最後的變化,它會覆蓋原來的文件中的變化。請記住,這更改原來的 - 如果這不是你想要的,你可以改變第二個sed輸出到${file}.tmp2,但你將不得不調整你的後續命令考慮到這一點。

如果你真的要刪除前九個後四個行的文件,你也可以使用類似:

head --lines=-4 oldfile.txt | tail --lines=+10 >newfile.txt 

只要你有一個[rd]ecent實施head/tailhead只打印最後四行,tail在第十行開始打印。

+0

你說得對,當我添加文件名時它沒有掛起。但是,仍然沒有行從文件的頭部或尾部被刪除。我不幸沒有一個體面的'head' ...我的意思是shell命令:) ...但我設法使用'tail'來擺脫標題和基於ant的正則表達式來剪切最後的行。 – user766353

+0

@ user766353,沒有行被刪除,因爲你沒有用'sed'的輸出替換文件。 「sed」通常會將更改寫入標準輸出(而不是更改原始文件)。你通常在輸出中看到的是那些改變,但是,由於你已經使用了'-n'來抑制默認的模式空間輸出,所以它們不會出現。查看我的更新以瞭解解決方案(確保文件本身已更新)。 – paxdiablo

0

更改第一行:

#!/bin/bash -x 

這將顯示您的每個命令的bash執行它,所有擴展都發生了。

我的猜測是$1/*.html不匹配任何文件;因此sed行的計算結果僅爲sed -n '1,9d',所以sed試圖從標準輸入讀取

+1

不,實際上它會擴展1美元(可能是一個空字符串)並保留'*'不變,在這種情況下,你會得到一個錯誤,除非你實際上擁有一個字面的'* .html'文件,不太可能,也不明智:-) – paxdiablo

+0

是的,@paxdiablo說了些什麼。 –

+0

但是@paxdiablo也說過,這裏的實際根本問題幾乎可以肯定它掛在第二個sed上。儘管使用'bash -x'是一種方便的故障排除技術。 –