Arrays 为什么管道输出到/dev/null和grep会污染我的bash数组?

Arrays 为什么管道输出到/dev/null和grep会污染我的bash数组?,arrays,linux,bash,shell,Arrays,Linux,Bash,Shell,我有两个shell脚本Linux/bin/bash,其中一个有一些用于查找文本等的公共函数,另一个使用这些公共函数并执行一些“实际”工作 当检查test2.sh中的数组变量oranges以测试/查看它是否是一个数组declare-p oranges 2>/dev/null | grep-q'^declare \-a'&&printf$fmt oranges是一个索引数组时,我偶然发现test1.sh中的另一个数组行突然被随机数污染了 我无法理解为什么会发生这种情况。有人有答案吗? 如果在使用脚本

我有两个shell脚本Linux/bin/bash,其中一个有一些用于查找文本等的公共函数,另一个使用这些公共函数并执行一些“实际”工作

当检查test2.sh中的数组变量oranges以测试/查看它是否是一个数组declare-p oranges 2>/dev/null | grep-q'^declare \-a'&&printf$fmt oranges是一个索引数组时,我偶然发现test1.sh中的另一个数组行突然被随机数污染了

我无法理解为什么会发生这种情况。有人有答案吗? 如果在使用脚本时使用echo或printf,则不会产生任何差异,前提是将错误传递到2>/dev/null并grep输出。我已经将脚本缩减到最基本的部分来显示问题。 另外,这个问题很容易解决,方法是将一行代码拆开,并将每个代码的输出分配给一个变量see test3.sh,这样我就不会陷入脚本编写或进一步的工作中。我一直在试图回答为什么会发生线路污染

test1.sh

#!/bin/bash

declare -a LINES

echo "::: DECLARE ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"
test2.sh

#!/bin/bash

source ./test1.sh

declare -a oranges=()
echo "::: test2-1 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"


declare -p oranges 2>/dev/null
echo "::: test2-2 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"


declare -p oranges 2>/dev/null | grep -E -i '^declare \-a'
echo "::: test2-3 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"


declare -p oranges 2>/dev/null | grep -E -i '^declare \-a' && printf "$fmt" "oranges is an indexed array"
echo "::: test2-4 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"

declare -p LINES
declare -p oranges 2>/dev/null | grep -E -i '^declare \-a' && printf "$fmt" "oranges is an indexed array" || printf "$fmt" "oranges is not an indexed array"
echo "::: test2-5 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"


declare -p oranges 2>/dev/null
echo "::: test2-6 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"
运行时,会出现以下输出:

::: DECLARE ::: Length of [LINES] is: 0, :::Content of [LINES] is: 
::: test2-1 ::: Length of [LINES] is: 0, :::Content of [LINES] is: 
declare -a oranges=()
::: test2-2 ::: Length of [LINES] is: 0, :::Content of [LINES] is: 
declare -a oranges=()
::: test2-3 ::: Length of [LINES] is: 1, :::Content of [LINES] is: 81
declare -a oranges=()
::: test2-4 ::: Length of [LINES] is: 1, :::Content of [LINES] is: 81
declare -a LINES=([0]="81")
declare -a oranges=()
::: test2-5 ::: Length of [LINES] is: 1, :::Content of [LINES] is: 81
declare -a oranges=()
::: test2-6 ::: Length of [LINES] is: 1, :::Content of [LINES] is: 81
test3.sh-解决方法

#!/bin/bash

source ./test1.sh

declare -a oranges=()
echo "::: test2-1 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"


someResult="$(declare -p oranges 2>/dev/null)"
thePattern="^declare \-a"

nextResult=`grep -E -i "$thePattern" <<< "$someResult"` || nextResult=""

if [[ -n "$nextResult" ]]
then
    echo "oranges is an indexed array"
else
    echo "oranges is NOT an indexed array"
fi

echo "::: test2-2 ::: Length of [LINES] is: ${#LINES[@]}, :::Content of [LINES] is: ${LINES[@]}"
LINES是一个保留变量,由shell填充,其行数可能适合终端窗口。使用shell未使用的其他变量名;看到了,它就会按预期工作

正如David C.Rankin在他的评论中提到的,所有大写变量通常都是为shell保留的,这就是为什么建议使用小写变量名的原因

如果出于某种原因必须使用变量的名称行,可以通过以下命令禁用checkwinsize选项作为解决方法;但这可能会有副作用,我不能保证它总是有效的

shopt -u checkwinsize
LINES是一个保留变量,由shell填充,其行数可能适合终端窗口。使用shell未使用的其他变量名;看到了,它就会按预期工作

正如David C.Rankin在他的评论中提到的,所有大写变量通常都是为shell保留的,这就是为什么建议使用小写变量名的原因

如果出于某种原因必须使用变量的名称行,可以通过以下命令禁用checkwinsize选项作为解决方法;但这可能会有副作用,我不能保证它总是有效的

shopt -u checkwinsize

这可以解释这种行为:

d。非交互式Shell现在对checkwinsize的设置作出反应 设定 前景作业退出后的行和列


这可以解释这种行为:

d。非交互式Shell现在对checkwinsize的设置作出反应 设定 前景作业退出后的行和列


来自

值得一提的是,所有大写变量通常都是为shell保留的,这就是为什么建议使用小写变量名的原因。。。可能想让他从xterm中尝试echo$行和echo$列,以了解冲突存在的原因:@user1934428它不是未设置的,但给定数组属性try foo=1;声明-一个foo;echo${foo[@]}。我对bash的内部结构了解不多,但您可以清楚地看到,当输出为TTY时,它会更新行和列变量,并且通过比较bash-c'LINES=;:;执行包含多个组件的管道;echo$LINES'到bash-c'行=;:|::;回音$行'。这里是bash 5.0.11顺便说一句,在manbash中@oguzismail,行和列都在解释性段落下面。shell使用以下变量。。。对于行,如果启用了checkwinsize选项或在交互式shell中,它将自动设置。。。我必须进一步深入——但shell使用意味着它可以在任何时候使用——我怀疑这就是导致问题中覆盖行为的原因。@oguzismail:也许我会联系终端应用程序的实现者。但是,tput行确实生成了正确的数字,因此,可能bash使用的机制与tput不同。@oguzismail nice!非常感谢!我忙于测试不同的场景,为什么我忽略了其他因素,比如Shell保留变量。为大家抽出时间深入研究这个问题并给出答复而干杯。我更新了我的数组变量名,一切正常。值得一提的是,所有大写的变量通常都是为shell保留的,这就是为什么建议使用小写的变量名。。。可能想让他从xterm中尝试echo$行和echo$列,以了解冲突存在的原因:@user1934428它不是未设置的,但给定数组属性try foo=1;声明-一个foo;echo${foo[@]}。我对bash的内部结构了解不多,但您可以清楚地看到,当输出是TTY时,它会更新行和列变量,并且通过比较bash-c的
行=;:;echo$LINES'到bash-c'行=;:|::;回音$行'。这里是bash 5.0.11顺便说一句,在manbash中@oguzismail,行和列都在解释性段落下面。shell使用以下变量。。。对于行,如果启用了checkwinsize选项或在交互式shell中,它将自动设置。。。我必须进一步深入——但shell使用意味着它可以在任何时候使用——我怀疑这就是导致问题中覆盖行为的原因。@oguzismail:也许我会联系终端应用程序的实现者。但是,tput行确实生成了正确的数字,因此,可能bash使用的机制与tput不同。@oguzismail nice!非常感谢!我忙于测试不同的场景,为什么我忽略了其他因素,比如Shell保留变量。为大家抽出时间深入研究这个问题并给出答复而干杯。我更新了我的数组变量名,一切正常。我注意到在你奇怪的输出错误的情况下,我们从来没有看到文本uOranges是一个索引数组,虽然这应该被打印,不是吗?我注意到在你奇怪的输出错误的情况下,我们从来没有看到文本oranges是一个索引数组,虽然这应该被打印,不是吗?