为什么我的变量在我的 bash while 循环中似乎没有增加?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5061227/
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-09-09 20:12:36  来源:igfitidea点击:

Why doesn't my variable seem to increment in my bash while loop?

bashshellvariablesscripting

提问by wwwilliam

I am fairly new to bash scripting. I can't seem to get the correct value of my counting variables to display at the end of of a whileloop in my bash script.

我对 bash 脚本很陌生。我似乎无法while在我的 bash 脚本中的循环结束时获得要显示的计数变量的正确值。

Background: I have a fairly simple task: I would like to pass a text file containing a list of file paths to a bash script, have it check for the existence of those files, and count the number of existing/missing files. I got most of the script to work, except for the counting part.

背景:我有一个相当简单的任务:我想将一个包含文件路径列表的文本文件传递给 bash 脚本,让它检查这些文件是否存在,并计算现有/丢失文件的数量。除了计数部分,我让大部分脚本都可以工作。

N=0
correct=0
incorrect=0
cat  | while read filename ; do
    N=$((N+1))
    echo "$N"

    if ! [ -f $filename ]; then

        incorrect=$((incorrect+1))
    else
        correct=$((correct+1))

    fi

done

echo "# of Correct Paths: $correct"
echo "# of Incorrect Paths: $incorrect"
echo "Total # of Files: $N"

If I have a list of 5 files, 4 of which exist, I expect to get the following output (note the echocommand within the whileloop):

如果我有 5 个文件的列表,其中 4 个存在,我希望得到以下输出(注意循环中的echo命令while):

1
2
3
4
5
# of Correct Paths: 4
# of Incorrect Paths: 1
Total # of Files: 5

Instead, I get:

相反,我得到:

1
2
3
4
5
# of Correct Paths: 0
# of Incorrect Paths: 0 
Total # of Files: 0

What happened to the values of these variables? Google had many suggestions of questionable quality and I think I could get it to work with a little more searching, but a brief explanation of what I'm doing wrong would be very helpful.

这些变量的值发生了什么变化?谷歌有很多质量有问题的建议,我想我可以通过更多的搜索来让它工作,但简要说明我做错了什么会非常有帮助。

回答by kurumi

This is because you are using the useless catcommand with a pipe, causing a subshell to be created. Try it without the cat:

这是因为您使用了cat带有管道的无用命令,导致创建了一个子 shell。尝试没有cat

while read filename ; do
    N=$((N+1))
    ....
done < file

回答by jlliagre

Alternatively, if you want to keep the catfor some reason, you can fix your script simply by adding this line before the catinstruction:

或者,如果您cat出于某种原因想保留,您可以通过在cat指令前添加以下行来修复您的脚本:

shopt -s lastpipe 

回答by Stephen Niedzielski

More generally, sometimes you want to pipe the output of a command. Here's an example that uses process substitutionto lint JavaScript files about to be committed by Git and counts the number of files that failed:

更一般地,有时您希望通过管道传输命令的输出。下面是一个示例,它使用进程替换来 lint 即将由 Git 提交的 JavaScript 文件并计算失败的文件数:

# $@ glob
git-staged-files() {
  git diff --cached -C -C -z --name-only --relative --diff-filter=ACMRTUXB "$@"
}

# $@ name
map() { IFS= read -rd $'##代码##' "$@"; }

declare -i errs=0
while map file; do
  echo "Checking $file..."
  git show ":$file"|
  eslint --stdin --stdin-filename "$file" || ((++errs))
done < <(git-staged-files \*.js)

((errs)) && echo -en "\e[31m$errs files with errors.\e[00m " >&2 || :