从 Bash 脚本到无限循环的 Bash 脚本

3
一个非常简单的“只运行一次”版本的我的脚本的例子:
./myscript.sh var1 "var2 with spaces" var3
#!/bin/bash
echo $1 #output: var1
echo $2 #output: var2 with spaces
echo $3 #output: var3

如预期工作!现在我尝试只启动脚本并在循环中输入变量,因为稍后我想一次复制多个数据集到shell。

./myscript.sh
#!/bin/bash  
while true; do
  read var1 var2 var3
  #input: var1 "var2 with spaces" var3
  echo $var1 #output: var1
  echo $var2 #output: "var2
  echo $var3 #output: with spaces" var3
done

看起来read命令是通过空格将输入分割,将所有剩余的内容放在最后一个变量中,对吗?有没有更好的方法在循环中添加变量?或者我如何让read命令表现得像我刚刚在脚本后面添加了这些变量一样?

那种循环的英文单词是什么?它可以在循环执行一个脚本的同时将不同的变量复制到shell中。如果我不知道它的名称,就无法在Google上搜索示例...


你的echo语句有一个小问题。你忘记在变量名前面加上"$"符号(例如,echo $var1)。 - EJK
抱歉,这个示例中有一个错误。已经修复了。 - eye
1
查找IFS变量。http://tldp.org/LDP/abs/html/internalvariables.html - user4453924
@眼 我认为使用这种变通方法将是完成此任务最简单的方式。 - user4453924
@BenGrimm 有很多原因不使用 eval。 - user4453924
显示剩余4条评论
1个回答

1
这段代码读取标准输入并将这些行解析为具有shell引用的参数:
# Clean input of potentially dangerous characters. If your valid input
# is restrictive, this could instead strip everything that is invalid
# s/[^a-z0-9" ]//gi
sed -ue 's/[][(){}`;$]//g' | \
while read input; do
  if [ "x$input" = "x" ]; then exit; fi      
  eval "set -- $input"
  # check argument count
  if [ $(( $# % 3 )) -ne 0 ]; then 
     echo "Please enter 3 values at a time"
     continue;
  fi

  echo $1
  echo $2
  echo $3
done

set -- $input 所有的魔法都在这里了。请参考Bash手册页面set

--
    If no arguments follow this option, then the positional parameters are   
    unset. Otherwise, the positional parameters are set to the arguments, 
    even if some of them begin with a ‘-’.

好的,不知道为什么,但是可以工作。你能解释一下 set -- $input 是什么意思吗?感谢你的帮助 :-) - eye
我建议使用IFS,因为使用eval是不好的实践。如果输入包含;,它将失败,不仅如此,其后的任何内容都将被执行。例如,如果它包含了 var1 "带空格的var2" var3;rm -rf /*,你可能会遇到一些麻烦。顺便说一句,任何读到这篇文章的人都不要尝试那样做。 - user4453924
所有是真的 - 我通常不会盲目地评估输入行,但这只是一个最小的情况。当然,他只是使用 REPL 来避免重复运行命令。 - Ben Grimm
哦,这是一个很大的安全问题。我一定需要做些什么来防止这种情况发生。也许只需在 eval 前删除每个分号或类似的东西 - 这个小程序将有三个人使用,不仅仅是我。顺便说一下 - 我是女孩 ^^ - eye
抱歉 :) 我在答案中增加了一个简单的输入过滤器。 - Ben Grimm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接