bash中的变量递增

时间:2011-09-20 08:54:36

标签: linux bash variables

考虑以下脚本:

#!/bin/bash

num=0
cat file | while read line; do
    echo "$line"
    lines[$num]="$line"
    ((num++))
    echo "num = $num"
done

echo "end num = $num"

i=0
while [ $i -lt $num ]; do
    echo "${lines[$i]}"
    ((i++))
done

通常,它应逐行读取文件,将结果存储在数组中,然后遍历数组并逐行打印。问题是变量$ num在第一个循环退出后以某种方式重置。我的这个脚本的输出如下(使用带有一些随机垃圾的文件):

dsfkljhhsdfsdfshdjkfgd
num = 1
fdfgdfgdfg
num = 2
dfgdfgdfgdfg
num = 3
dfgdfgdfgdfgdfg
num = 4
dfgdfgdfgdfgdfgd
num = 5
fgdfgdfgdfg
num = 6
dfgdfgdfgdfg
num = 7
dfgdfgdfgdfgdfg
num = 8
dfgdfgdfgdfg
num = 9
dfgdfgdgdgdg
num = 10
dfgdffgdgdgdg
num = 11
end num = 0

这是为什么?如何记住变量?我在SUSE Linux 10上使用bash 3.1.17。

3 个答案:

答案 0 :(得分:15)

为什么呢?这是因为:

cat file | while read line; do
    echo "$line"
    lines[$num]="$line"
    ((num++))
    echo "num = $num"
done

在一个单独的进程中运行while语句,该进程具有自己的环境,而不是触及父环境。同样地,您会发现lines数组也不存在。

以下简化脚本显示了这一点:

#!/bin/bash
export xyzzy=42
echo urk | while read line; do
    xyzzy=999
    echo $xyzzy
done
echo $xyzzy

该脚本的输出是:

999
42

因为变量设置为999是在子流程中完成的。

最重要的是,如果您希望信息反映在当前流程(脚本)中,您需要在脚本中执行工作,或者找一些其他方法来获取信息子过程。

如果您使用输入重定向而不是启动子流程管道,它应该可以按您的需要工作。那是因为while位然后在当前进程的上下文中完成,而不是在管道中的单独进程。例如:

#!/bin/bash
export xyzzy=42
while read line; do
    xyzzy=999
    echo $xyzzy
done <<EOF
hello
EOF
echo $xyzzy

将产生:

999
999

针对您的具体情况,请替换:

done <<EOF
hello
EOF

使用:

done <file

答案 1 :(得分:3)

要添加到上一个答案:并且为了避免(和UUOC),你需要这样的东西:

while ...; do
  ...
done < file

答案 2 :(得分:0)

只需将变量保存在同一环境中即可。在第4行,删除“cat file |”。在第9行,追加“&lt; file”。你的结束数现在将包含预期的11,而lines数组将通过你的第二个循环一次打印一个元素。