分配变量后,稍后使用变量引用扩展字符串

时间:2018-09-21 01:19:36

标签: linux bash

我正在尝试将两个包含名称(如果有)和电子邮件的列表与bash(外壳)中的标准电子邮件文本合并 (我必须删除不相关的代码,因为其中包含一些私人信息,因此其中一些代码可能看起来并不有用。)

代码的前半部分检查是否有名称列表和电子邮件列表。 如果没有可用的名称,后半部分将仅合并电子邮件地址和文本;如果可用的名称列表,则还会“尝试”合并名称,电子邮件和文本。

f1 =电子邮件列表,f2 =姓名列表。 正如您在下面的代码的前半部分看到的那样,如果列表可用,则$ f2应该显示名称,但是在日志文件中则不显示任何内容。

我一直在努力解决此问题两天,但没有任何效果。当名称可用时,它总是输出为“ Hello ...” ,而应为“ Hello John D ...”


#FIRST HALF
if [ "$names" = "no" ]
then
    text="Hello..."

elif [ "$names" = "yes" ]
then
    text="Hello $f2..."
fi

#SECOND HALF
if [ "$names" = "no" ]
then
for i in $(cat $emaillist); do
    echo "$text" >> /root/log
    echo "$i" >> /root/log
done

elif [ "$names" = "yes" ]
then
    paste $emaillist $namelist | while IFS="$(printf '\t')" read -r f1 f2
do
    echo "$text" >> /root/log
    echo "$f1" >> /root/log
done
fi

1 个答案:

答案 0 :(得分:0)

运行text="Hello $f2"时,在分配时会在{em>上查找$f2 ;精确的字符串已分配给text,以后仅在echo "$text"上使用该精确的字符串。

这是非常可取的行为:如果shell变量的值可以运行任意代码,则不可能编写可以安全地处理不受信任数据的shell脚本...但这确实意味着实现程序需要进行一些更改。


如果您要推迟评估(在扩展时查找$f2的值而不是赋值),请不要完全使用shell变量:请改用函数。

case $names in
  yes) write_greeting() { echo "Hello $name..."; };;
  *)   write_greeting() { echo "Hello..."; };;
esac

while read -r name <&3 && read -r email <&4; do
    write_greeting
    echo "$email"
done 3<"$namelist" 4<"$emaillist" >>/root/log

上面的代码中的一些增强功能:

  • 您不需要paste即可同步地从两个流中读取数据;您可以简单地在不同的文件描述符上打开它们(上面已选择了FD 34;仅保留了0、1和2,因此也可能选择了更大的数字),并使用单独的{ {1}}命令。
  • 在整个循环中仅打开输出接收器一次(通过将重定向放在read之后)比每次您想写一行都重新打开输出接收器效率更高。
  • 总是引用诸如done"$namelist"之类的扩展名;如果处理带有不寻常字符(包括空格和glob表达式)的文件名,或者"$emaillist"为非默认值,这将使代码更加可靠。