【问题标题】:bash script: looping over arguments [duplicate]bash脚本:循环参数[重复]
【发布时间】:2013-08-24 10:13:08
【问题描述】:

我编写了一个脚本 (replace.sh) 将 ~ 替换为 ~\n。我想知道如何使用多个参数调用此脚本。

#!/bin/bash

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

例如我想调用 ./replace.sh text1 text2。它无法读取

text1的内容是:1~1~1,调用脚本后应该是

1 ~
1 ~
1 ~

【问题讨论】:

标签: shell unix sed


【解决方案1】:

这就足够了:

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

注意:shell for 循环的 in ... 部分是可选的。不使用时,for 默认选择所有参数(即"$@"),这正是您所期望的。

【讨论】:

  • 请不要推荐没有后缀的-i。这意味着没有备份。没有备份->很可能哎哟。另外,如果您在没有in <x> 的shell 脚本中使用for 循环,也许可以解释这意味着什么?
  • 答案使用更便携的解决方案 (POSIX) 更新,该解决方案处理备份备注,尽管运行多个脚本会导致 xxx.bak.bak 文件,而第一次运行将覆盖潜在的现有备份。 ..
  • @jiliagre +1 感谢您的更新/澄清。 (我听到你多次运行,但仍然认为向新脚本编写者提及 .bak 总是值得的。自从我第一次学习 Perl 单行代码以来,我的宠物问题。
  • 更精细的点;没有备份的编辑很痛苦。
【解决方案2】:

其他答案涵盖了您的真正问题。但值得多说的一件事是$*$@ 在双引号时的扩展方式有何不同。 tl;dr 你几乎总是想要"$@"

"$*" 扩展为单个字符串,其中包含所有参数,其中第一个字符为IFS。在实践中,这通常意味着所有参数作为一个由空格分隔的字符串。因此,如果您的参数是file1.txtfile2.txtfile3.txt,那么"$*" 将其作为一件事 传递给循环,即file1.txt file2.txt file3.txt。当然,那一件事本身并不存在。

"$@" 扩展为每个参数,一次一个,被视为一个“单词”。这很好,因为它将前面示例中的file1.txtfile2.txtfile3.txt 正确地视为三个项目。循环将一次正确地接收它们。此外,"$@" 很好,因为即使你的文件名中有空格,你也会得到正确的行为,因为循环会处理,例如filename 1filename 2filename 2 and a half 为三项,一项一项。 (通常,shell 将空格视为单词的结尾,因此filename 1 在 shell 中看起来像 两个项目filename1

如果$@$* 都没有被引用,则扩展所有位置参数的单词。所以在这种情况下,它们实际上是相同的(而且都是一个坏主意,因为它们不能保护你免受奇怪命名的文件的影响)。

这里有一个很好的可视化所有可能性:http://wiki.bash-hackers.org/scripting/posparams#mass_usage

【讨论】:

  • 我认为您应该在答案中包含双引号,因为这两个变量在未引用时也具有含义(实际上是相同的含义)。您可能还想涵盖答案中未引用的含义。就目前而言:$* 扩展为单个字符串 不正确;它应该是 "$*" 扩展为单个字符串 ...是的,您在上一段中提到了双引号,但在下一段中省略它们会产生误导。
  • @JonathanLeffler 你说得对。不知道我怎么了。我应该包括引号,我会提到未引用的版本。
  • 嘿telemachus。我有一种感觉“$*”确实扩展为一个字符串,感谢您确认和解释幕后发生的事情。
【解决方案3】:

在你的 for 循环中使用 "$@"

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

虽然我不确定 sed 是否在做您在此处描述的操作。

【讨论】:

  • 正是我需要的!至于sed,应该是's/~/\\n/g'
  • 完全不使用in "$@"来节省一些击键...
  • @jiliagre 我认为这是一个更简洁的情况。很多人不知道单独for i 意味着in "$@"。需要额外输入 7 个字符,但清晰的回报是巨大的。
  • 同意。许多人不知道in "$@" 与通常的ìn $* 意味着什么。这就是为什么我更喜欢建议使用恕我直言更容易记住的空表单的原因。
猜你喜欢
  • 1970-01-01
  • 2011-06-13
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多