Linux bash中的变量递增

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7482510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 06:17:12  来源:igfitidea点击:

Variable incrementing in bash

linuxbashvariables

提问by petersohn

Consider the following script:

考虑以下脚本:

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

Normally, it should read the file line by line, store the result in an array, then go through the array and print it line by line. The problem is that the variable $num resets somehow after the first loop exits. The output of this script for me is the following (using a file with some random garbage in it):

通常,它应该逐行读取文件,将结果存储在数组中,然后遍历数组并逐行打印。问题是变量 $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

Why is this? How do I achieve to remember the variable? I am using bash 3.1.17 on SUSE Linux 10.

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

采纳答案by paxdiablo

Why? It's because this:

为什么?这是因为:

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

runs the whilestatement in a separate process, with its own environment, not touching the parent environment. You'll find, similarly, that the linesarray is not there either.

while在单独的进程中运行语句,有自己的环境,不涉及父环境。同样,您会发现lines数组也不存在。

The following simplified script shows this in action:

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

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

The output of that script is:

该脚本的输出是:

999
42

because the setting of the variable to 999is done in the subprocess.

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

Bottom line, if you want information to be reflected in the current process (the script), you'll need to do the work inthe script or find some other way to get the information out of the sub-process.

最重要的是,如果您希望信息反映在当前流程(脚本)中,您需要脚本中完成工作或寻找其他方法从子流程中获取信息。

If you use input redirection rather than starting a sub-process pipeline, it should work as you want. That's because the whilebit is then done in the context of the currentprocess rather than a separate process in a pipeline. For example:

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

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

will produce:

将产生:

999
999

For your specific case, replace:

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

done <<EOF
hello
EOF

with:

和:

done <file

回答by Dimitre Radoulov

To add to the previous answer: and to avoid that (and the UUOC), you'll need something like this:

要添加到上一个答案:并避免这种情况(和 UUOC),您需要这样的东西:

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

回答by Daniel Liston

Simply keep your variables all in the same environment. On line 4, remove "cat file | ". On line 9, append " < file". Your end num will now contain the expected 11, and the lines array will print one element at a time via your second loop.

只需将所有变量保持在相同的环境中即可。在第 4 行,删除“cat 文件 |”。在第 9 行,附加“<file”。您的结束编号现在将包含预期的 11,并且行数组将通过您的第二个循环一次打印一个元素。