bash中的数组内容在直接调用时是可以的,但是从函数调用时会丢失

时间:2014-11-27 20:45:16

标签: arrays bash shell loops ifs

我正在尝试使用xmllint搜索xml文件并将我需要的值存储到数组中。这就是我在做的事情:

#!/bin/sh

function getProfilePaths {
    unset profilePaths
    unset profilePathsArr
    profilePaths=$(echo 'cat //profiles/profile/@path' | xmllint --shell file.xml | grep '=' | grep -v ">" | cut -f 2 -d "=" | tr -d \")
    profilePathsArr+=( $(echo $profilePaths))
    return 0
}

我有另一个功能:

function useProfilePaths {
    getProfilePaths
    for i in ${profilePathsArr[@]}; do
    echo $i
    done
    return 0
}

useProfilePaths

函数的行为会改变我是否在命令行上手动执行命令VS从不同的函数调用它们作为包装器脚本的一部分。当我从包装脚本中获取函数时,数组中的项是1,与从命令行执行时相比,它是2:

$ echo ${#profilePathsArr[@]}
2

当回显时,profilePath的内容如下所示:

$ echo ${profilePaths}
/Profile/Path/1 /Profile/Path/2

我不确定xmllint调用的分隔符是什么。

当我从包装器脚本调用我的函数时,for循环的第一次迭代的内容如下所示:

for i in ${profilePathsArr[@]}; do
    echo $i
done

第一个回声看起来像:

/Profile/Path/1
/Profile/Path/2

......第二个回音是空的。

任何人都可以帮我调试这个问题吗?如果我能找出xmllint使用的分隔符是什么,也许我可以在数组中正确解析项目。

仅供参考,我已经尝试了以下方法,结果相同:

profilePaths=($(echo 'cat //profiles/profile/@path' | xmllint --shell file.xml | grep '=' | grep -v ">" | cut -f 2 -d "=" | tr -d \"))

3 个答案:

答案 0 :(得分:0)

您应该使用正确的--shell开关,而不是使用--xpath开关和许多管道。

但据我所知,当你有多个值时,没有简单的方法来分割不同的节点。

所以解决方案就是这样迭代:

profilePaths=(
    $(
        for i in {1..100}; do
            xmllint --xpath "//profiles[$i]/profile/@path" file.xml || break
        done
    )
)

或使用

profilePaths=( $(xmlstarlet sel -t -v "//profiles/profile/@path" file.xml) )

默认显示带换行符的输出

答案 1 :(得分:0)

您遇到的问题与数据封装有关;具体而言,函数中定义的变量是本地的,因此除非您另外定义它们,否则无法在该函数之外访问它们。

根据您使用的sh的实施情况,您可以通过在变量定义上使用eval或使用global等修饰符来解决此问题。 {1}}和mksh declare -gzsh。我知道bash的实施肯定有效。

答案 2 :(得分:0)

感谢您就如何解决此问题提供反馈。在进行了更多调查之后,我通过改变我迭代我的' profilePaths'的内容的方式来完成这项工作。变量将其值插入' profilePathsArr'阵列:

# Retrieve the profile paths from file.xml and assign to 'profilePaths'
profilePaths=$(echo 'cat //profiles/profile/@path' | xmllint --shell file.xml | grep '=' | grep -v ">" | cut -f 2 -d "=" | tr -d \")

# Insert them into the array 'profilePathsArr'
IFS=$'\n' read -rd '' -a profilePathsArr <<<"$profilePaths"

出于某种原因,使用来自我的主脚本的所有不同函数调用以及对其他脚本的调用,似乎分离器在此过程中丢失了。我无法找到根本原因,但我知道通过使用&#34; \ n&#34;作为IFS和while循环,它就像一个魅力。

如果有人希望就此添加更多评论,那么非常欢迎您。