2013-08-21 176 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