2013-08-21 174 views
2

我編寫了一個用〜\ n代替〜的腳本(replace.sh)。我想知道如何用多個參數來調用這個腳本。bash腳本:循環參數

#!/bin/bash 

for i in "$*" 
do 
    sed 's/~/~\n/g' "$i" 
done 

例如,我想調用./replace.sh text1 text2。它不能讀取

text1中的內容有:1〜1〜1調用腳本後,它應該是

1 ~ 
1 ~ 
1 ~ 
+0

有關'$ *'和'$ @'之間區別的更多信息,請參閱此處:http://mywiki.wooledge.org/BashGuide/Parameters#Special_Parameters_and_Variables。這對於s​​hell腳本來說很微妙但非常重要。 – Telemachus

回答

4

使用"[email protected]"在for循環:

for i in "[email protected]" 
do 
    sed -i.bak 's/~/~\n/g' "$i" 
done 

雖然我不確定sed是否正在按照您在此處描述的內容進行操作。

+0

正是我需要的!至於sed,它應該是/〜/ \\ n/g' – Paolo

+0

通過不使用'in「$ @」'來保存一些擊鍵...... – jlliagre

+1

@jiliagre我認爲這是一個情況, 。很多人不知道「$ @」'中單獨暗示了'我爲什麼'。這是一個額外的7個字符鍵入,但清晰度的回報是巨大的。 – Telemachus

2

這應該足夠了:

for i do 
    sed -i.bak 's/~/~\n/g' "$i" 
done 

這裏的便攜式變種應該與任何符合POSIX標準shellsed工作:

for i do 
    sed 's/~/~\n/g' "$i" > "$i.bak" && cp "$i.bak" "$i" 
done 

注:該膠囊的in ...部分for環是可選的。不使用時,for默認選擇所有參數(即"[email protected]"),這正是您所期望的。

+1

請不要推薦沒有後綴的'-i'。這意味着沒有備份。沒有備份 - >很可能哎。另外,也許你可以解釋一下,如果你在shell腳本中使用'for'循環,而不是'in ',這意味着什麼? – Telemachus

+0

答案更新了處理備份備註的更便攜的解決方案(POSIX),儘管運行腳本不止一個將導致xxx.bak.bak文件,而第一次運行將覆蓋潛在的現有備份... – jlliagre

+1

@jiliagre +1感謝您的更新/澄清。 (我聽說你在多次運行,但仍然認爲總是值得一提的是'.bak'給新的腳本編寫者。自從我第一次學習Perl單行程以來,我的寵物問題。 – Telemachus

1

其他答案涵蓋了你真正的問題。但值得一提的是,如果雙引號,$*[email protected]在擴展方面有所不同。 tl; dr你幾乎總是想要"[email protected]"

"$*"擴展爲包含所有與IFS在它們之間的第一個字符的參數的單個串。實際上,這通常意味着所有參數都是由空格分隔的一個字符串。所以如果你的參數是file1.txt,file2.txtfile3.txt,那麼"$*"把那個循環當作一件事,即file1.txt file2.txt file3.txt。當然,這件事並不存在。

"[email protected]"擴展到每個參數,一次一個,被視爲一個單詞「單詞」。這很好,因爲它會將前面的示例中的file1.txt,file2.txtfile3.txt正確地視爲三項。循環將一次正確接收它們。另外,"[email protected]"是很好的,因爲即使你的文件名中有空格,你也會得到正確的行爲,因爲循環會處理,例如, filename 1,filename 2,filename 2 and a half三個項目,一個接一個。 (一般情況下,殼把一個空間標誌着單詞的結尾,所以filename 1看起來像兩個項目的外殼,filename1

當他們中沒有報價都[email protected]$*擴大的話所有的位置參數,所以在這種情況下,它們實際上是相同的(並且這是一個壞主意,因爲它們不能保護您不受奇怪命名的文件的影響)。

這裏有一個很好的可視化的所有可能性:http://wiki.bash-hackers.org/scripting/posparams#mass_usage

+0

我想你應該在你的答案中包含雙引號,因爲這兩個變量在沒有引用時也有意義(事實上具有相同的含義),你可能還想覆蓋答案中沒有引用的含義。一個string_不正確;它應該是_'「$ *」'擴展爲單個字符串_是的,你在前面的段落中提到了雙引號,但是在下一個段落中忽略它們是誤導性的。 –

+0

@JonathanLeffler你是絕對正確,不知道我有什麼問題,我應該包括引號,我會提到沒有引號的版本。 – Telemachus

+0

嗨telemachus。我有一種感覺「$ *」確實擴展爲單個字符串,這要感謝您確認並解釋幕後發生了什麼事。 – Paolo