variables值在子shell中丢失

这个bash脚本将jar文件的名字连接到一个类path(variablesCP),在while循环中,这个值是正确的,但是在子shell中丢失了,就像这个相关的问题中描述的那样。Bash variables作用域

#!/bin/bash CP="AAA" func() { ls -1 | while read JAR do if [ ! -z "$CP" ]; then CP=${CP}':' fi CP=${CP}${JAR} done echo $CP # <-- prints AAA } func 

我的问题是,由于我不知道哪一个元素是最后一个元素,那么值怎么保存。

我是否真的必须将当前值(在循环中重复)保存到文件中?

编辑:

一位同事想出了这个很好的命令序列

 ls | xargs echo|tr ' ' : 

这里的问题是,在管道中使用while会创建一个子shell,并且子shell不会影响其父级。 你可以用几种方法解决这个问题。 对于你现在正在做的事情,这就足够了:

 for JAR in *; do # Your stuff done 

另外要注意的是,你不应该依赖解析ls

这也向你展示了避免subshel​​l的方法。

你可能会发现使用更多功能。

例如:

 export CP=$( find /home/depesz/q/ -maxdepth 1 -type f -name '*.jar' -printf ':%p' | cut -b 2- ) 

当然,一组查找选项取决于你需要什么。

这一个更接近你以前的东西:

 export CP=$( find . -maxdepth 1 -type f -name '*.jar' -printf ':%f' | cut -b 2- ) 

隐含的子壳令人困惑; 总是使用圆括号将其明确。 要解决你的问题,只需要移动子shell中的回声。

 #!/bin/bash CP="AAA" func() { ls -1 | ( while read JAR do if [ ! -z "$CP" ]; then CP=${CP}':' fi CP=${CP}${JAR} done echo $CP ) } func 

这是另一个解决方案,它完全避免了子shell的产生。 关键是将循环输入捕获到一个变量中(在我的例子中称为“JARS”),然后使用<< EOF将该变量重定向到循环中:

 JARS=$(ls -1) while read JAR do if [ ! -z "$CP" ]; then CP=${CP}':' fi CP=${CP}${JAR} done <<EOF $JARS EOF echo $CP 

这些答案似乎都没有得到真正正确的返回值,用一个非常简单的例程回应答案是好的,但是说你想要脚本的输出,这是没用的。 我没有最好的答案,但我没有太多的时间来弄清楚,所以我只是建议输出你想要的临时文件,并阅读(惊讶它并没有迄今为止提到):

 #!/bin/bash CP="AAA" func() { ls -1 | ( while read JAR do if [ ! -z "$CP" ]; then CP=${CP}':' fi CP=${CP}${JAR} done echo "$CP" > /tmp/cp-value-file ) } func CP=$(cat /tmp/cp-value-file) echo $CP 

下行:在某些情况下需要在循环的每一次迭代中写入磁盘。