变量值在子shell中丢失

时间:2010-06-21 14:31:00

标签: bash unix scripting

此bash脚本将jar文件的名称连接到类路径(变量CP),在while循环中值正确但在子shell中丢失,如此相关问题中所述Bash variable scope

#!/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 ' ' :

5 个答案:

答案 0 :(得分:6)

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

for JAR in *; do
    # Your stuff
done

另外需要注意的是shouldn't rely on parsing ls

This还会向您展示避免子shell的方法。

答案 1 :(得分:1)

您可能会发现使用find更具通用性。

例如:

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- )

答案 2 :(得分:0)

隐含的子弹令人困惑;总是通过使用括号使它们明确。要解决您的问题,只需在子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

答案 3 :(得分:0)

这是另一种解决方案,它可以完全避免产生子shell。关键是将循环输入捕获到变量中(在我的示例中称为“JARS”),然后使用&lt;&lt;&lt;&lt; EOF:

JARS=$(ls -1)

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

echo $CP

答案 4 :(得分:0)

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

#!/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

下行:在某些情况下,每次迭代都需要写入磁盘。