Bash在分隔符上拆分字符串,将段分配给数组

Bash在分隔符上拆分字符串,将段分配给数组,bash,python,osx,Bash,Python,Osx,在中,我想将可能包含空格分隔元素的类似路径的环境变量转换为数组,确保包含空格的元素不会导致单词分裂,显示为“多个元素” 让PATH\u变量成为所讨论的变量 让un:dodecadro:per:tirre:per:i danni作为变量的内容 所需的数组\u应具有6个元素,而不是7个 0) un 1) dodecaedro 2) per 3) tirare 4) per 5) i danni “棘手”条目可能是空格分隔的值:i danni 我正在寻找绝对最优雅的和正确的方法来实现这一点 限制:

在中,我想将可能包含空格分隔元素的类似路径的环境变量转换为
数组
,确保包含空格的元素不会导致单词分裂,显示为“多个元素”


PATH\u变量
成为所讨论的变量

un:dodecadro:per:tirre:per:i danni
作为变量的内容

所需的
数组
\u应具有
6个
元素,而不是
7个

0) un
1) dodecaedro
2) per
3) tirare
4) per
5) i danni
“棘手”条目可能是空格分隔的值:
i danni

我正在寻找绝对最优雅的正确的方法来实现这一点

限制:它必须与我的版本配合使用:
v3.2.48(1)-发行版


在这方面做得非常漂亮:

工作。显示我在寻找什么


在我们的爱人身上,最好的方法是什么

您能否具体改进我的尝试
4

这是我的尝试
#/bin/bash
PATH_VARIABLE='un:dodecadro:per:tirre:per:i danni'
#错
a1=($(echo$PATH_变量| tr':''\n'))
#错
a2=($(
读取路径_组件时;执行以下操作
回显“$path\U组件”
完成<
修改Jim McNamara的答案,您只需重置IFS:

oIFS="$IFS"
foo='un:dodecaedro:per:tirare:per:i danni'
IFS=: arr=( $foo )
IFS="$oIFS"
我更喜欢函数作用域,因为它可以保护IFS更改不流入全局作用域,而无需特别小心地重置它

编辑和解释: 澄清一下:在第二个示例中,IFS设置确实改变了全局变量。这两者之间的显著区别是:

IFS=: arr=( $foo )
这是:

IFS=: read -a arr <<< "$foo"
考虑:

$ foo='1:2 3:4 5:6'
$ IFS=':'; arr=($foo)
$ echo "${arr[0]}"
1
$ echo "${arr[1]}"
2 3
$ echo "${arr[2]}"
4 5
$ echo "${arr[3]}"
6
哦,好吧-我花了太长时间来格式化答案…+1@kojiro。

#对。如果路径成员可能包含换行符,请添加-d“”。
# Right. Add -d '' if PATH members may contain newlines.
IFS=: read -ra myPath <<<"$PATH"

# Wrong!
IFS=: myPath=($PATH)

# Wrong!
IFS=:
for x in $PATH; do ...

# How to do it wrong right...
# Works around some but not all word split problems
# For portability, some extra wrappers are needed and it's even harder.
function stupidSplit {
    if [[ -z $3 ]]; then
        return 1
    elif [[ $- != *f* ]]; then
        trap 'trap RETURN; set +f' RETURN
        set -f
    fi
    IFS=$3 command eval "${1}=(\$${2})"
}

function main {
    typeset -a myPath
    if ! stupidSplit myPath PATH :; then
        echo "Don't pass stupid stuff to stupidSplit" >&2
        return 1
    fi
}

main

IFS=:read-ra myPath 3.2.48-1-Apple,Mac OS X?我的shell报告3.2.48(1)用括号而不是破折号,所以可能不是。为什么前两个选项对你不起作用?它们对我都起作用(我不希望第二个起作用,因为我有一种错觉,我的bash不支持进程替换
的确,Mac OS X“美洲狮”。智力奴役。征服的工具。无论如何,
a1
a2
分裂成
7
元素,而不是
6
。对吗?啊……指出这些微妙之处,让人们知道为什么表面上显而易见的答案不是你想要的答案。我添加了一个“我的环境”部分!:)这句话对我有用:
IFS=:foo=($1)
6
元素。在分配任务之前没有
。将其更改为
foo=($1)
->
2
元素。您可以尝试/报告结果吗?
IFS=:foo=($1)
有效“,但是没有函数作用域会很混乱,因为它会将IFS的值溢出到全局作用域中。但是,有了函数控制作用域,您不需要把事情放在一行上。不在我的系统上。请检查并让我们知道……(我试过:GNU/Linux(内核3.5.0-25-generic)Ubuntu 12.10
bash
v4.2.37(1)-
IFS
没有“溢出”到作业前指定的一条语句之外。@Robottinosino没有什么?请澄清您的要求。我认为您编写的内容可以更简洁:
IFS=:foo=($1)
我说,IFS
不能通过在数组赋值前加前缀来进行全局设置。我还说,更“简洁”没有其他不利影响那样。在函数中使用与否。太棒了。为什么它在底部?幸好我一直在滚动…我知道这个任务有一个优雅的单行线。就像shell中的大多数任务一样。
IFS=: read -a arr <<< "$foo"
$ echo "$BASH_VERSION"
3.2.48(1)-release
$ echo "$IFS"


$ foo='un:dodecaedro:per:tirare:per:i danni'
$ IFS=: read -a arr <<< "$foo"
$ echo "${#arr[@]}"
6
$ echo "$IFS"


$ IFS=: arr1=( $foo )
$ echo "${#arr1[@]}"
6
$ echo "$IFS"
:
$ foo='1:2 3:4 5:6'
$ IFS=':'; arr=($foo)
$ echo "${arr[0]}"
1
$ echo "${arr[1]}"
2 3
$ echo "${arr[2]}"
4 5
$ echo "${arr[3]}"
6
# Right. Add -d '' if PATH members may contain newlines.
IFS=: read -ra myPath <<<"$PATH"

# Wrong!
IFS=: myPath=($PATH)

# Wrong!
IFS=:
for x in $PATH; do ...

# How to do it wrong right...
# Works around some but not all word split problems
# For portability, some extra wrappers are needed and it's even harder.
function stupidSplit {
    if [[ -z $3 ]]; then
        return 1
    elif [[ $- != *f* ]]; then
        trap 'trap RETURN; set +f' RETURN
        set -f
    fi
    IFS=$3 command eval "${1}=(\$${2})"
}

function main {
    typeset -a myPath
    if ! stupidSplit myPath PATH :; then
        echo "Don't pass stupid stuff to stupidSplit" >&2
        return 1
    fi
}

main