【问题标题】:bash variables - understanding scope after while loopbash 变量 - 在 while 循环后理解范围
【发布时间】:2023-03-08 20:11:01
【问题描述】:

我有一个简单的 bash 脚本,如下所示。它以 csv 文件作为第一个参数。

#!/bin/bash

x="John"
y="Dan"
z="Steve"

echo "x -- $x"
echo "y -- $y"
echo "z -- $z"

INPUT=$1
OLDIFS=$IFS
IFS=,
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 1; }
while read x y z
do
        echo "x: $x"
        echo "y: $y"
        echo "z: $z"
done < $INPUT
IFS=$OLDIFS

echo "x -- $x" #no value?
echo "y -- $y" #no value?
echo "z -- $z" #no value?

我想知道为什么在 while 循环运行后变量 x、y 和 z 不包含任何字符串值?我知道 while 循环会在本地更改 x、y 和 z 的值。但是,我希望 x、y 和 z 在 while 循环保持其最初声明的值之后分别为“John”、“Dan”和“Steve”。或者至少,保存 csv 解析循环给它的最后一个值,而不是空的。

while 循环是否会创建原始脚本上下文的子进程,然后继续该子进程?提前感谢您的解释。

编辑#1

为上下文添加 csv 文件以防万一有人想运行它:

'P1','2014-10-31',0
'P1','2014-11-01',0
'P2','2014-11-07',0
'P2','2014-11-08',0
'P3','2014-11-14',0
'P3','2014-11-15',0
'P1','2014-11-21',1
'P1','2014-11-22',1
'P2','2014-12-05',1
'P2','2014-12-06',1
'P3','2014-12-12',1
'P3','2014-12-13',1

【问题讨论】:

  • 没有。它替换循环中全局变量的内容。如果你想让它做,否则将循环放在一个函数中,并制作 x,yz local
  • 顺便说一句,您不必保存/恢复 IFS。像这样调用您的读取:while IFS=, read x y z 仅将其设置为 while。
  • @ElliottFrisch 如果它替换了全局变量,为什么不将它们设置为脚本末尾 csv 文件最后一行中的值?它们只是空的。
  • 因为 csv 文件的结尾导致脚本将 全局变量 设置为空。

标签: bash variables while-loop pipe subprocess


【解决方案1】:

while 语句(以及它执行的read 命令)在同一个 shell 中执行。但是,read 将设置 x 等的值。到它读取的任何内容,包括它在输入末尾看到的空/空行,这会导致它以非零状态退出。

如果您想在没有可用输入时保留变量的值,则必须在read 中使用不同的变量,并设置x 等。在循环体中。

while read a b c; do
    x=$a
    y=$b
    z=$c
done < "$INPUT"

现在,abc 仍然是全局变量,但 xyz 只有在 read 成功时才会修改。

【讨论】:

    【解决方案2】:

    我相信这里发生的事情是读取失败,并在 while 循环结束时填充变量而没有任何内容。它们仍然应该在范围内。

    澄清: 尝试读取时读取失败,并且在到达文件末尾时没有任何内容可读取。此时,while 循环退出,变量被清除(尽管变量仍在作用域内)。

    【讨论】:

    • 其实我查了一下,read 会清除其变量的值,即使它没有读取输入:x=3; read x &lt; /dev/null 会将x 设置为空字符串。
    • @gniourf_gniourf 当然读取失败,否则while循环将永远运行。
    • 文档不清楚(甚至检查 POSIX 规范),但read 似乎在尝试从其输入读取之前将由其参数命名的变量设置为空字符串。这在bashdash 的多个版本中得到了证实。
    • 我不认为读取失败。那么你是说'read'会简单地删除变量值吗?或者它不会只是将变量设置为 csv 文件的最后一行(为上下文添加)?
    • @gniourf_gniourf 听起来更好。在文件末尾读取“读取”一个空行,处理完之后,read 以状态 1 退出。
    猜你喜欢
    • 1970-01-01
    • 2013-02-25
    • 2016-01-24
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多