将Python数据列表转换为Bash数组

21
我有一个Bash脚本,像这样调用了一个Python脚本:


OUTPUT=$(python /path/path/script.py attr attr attr);

Python脚本将返回一个类似如下的数据列表:

[item1, item2, item3]

我该如何将$OUTPUT变量(一个返回Python数据列表的字符串)转换为Bash数组?

如果可能的话,我想在Bash中逐个读取每个项目。


我能够从Python中检索字符串,我想知道如何将该字符串转换为Bash数组。 - Altus
如果您能够修改Python脚本以更改其输出,则可以使其更易于处理较多的可能输出值,并且更加安全。否则,您必须对输出允许的内容进行断言。 - Etan Reisner
这就是我遇到的问题,我不被允许更改输出,这是一个很尴尬的任务分配给我的 :( - Altus
5个回答

42

添加()| tr -d '[],'

OUTPUT=($(python /path/path/script.py attr attr attr | tr -d '[],'))

echo ${OUTPUT[0]}
echo ${OUTPUT[1]}
echo ${OUTPUT[2]}
echo ${OUTPUT[@]}

输出:

item1
item2
item3
item1 item2 item3

8
如果数组元素包含空格,事情会变得更加复杂。 - glenn jackman
1
@glennjackman:是的,这个解决方案不适用于带有空格的项。 - Cyrus
3
使用bash >= 4.0,这适用于带有空格的项目:mapfile -t OUTPUT < <(python /path/path/script.py attr attr attr | sed 's/[][]//g;s/, /\n/g') - Cyrus
1
为了确保清晰,展示script.py的内容会很有帮助。 - amc

9
你可以让你的script.py打印一个字符串,每个条目之间用空格分隔,Bash会将其转换为数组;或者你可以使用Bash将python脚本的返回值转换为所需的格式。
如果你选择从script.py中打印字符串,你可以使用以下python代码:
returnList = [1, 2, 3]
returnStr = ''
for item in returnList:
    returnStr += str(item)+' '
print(returnStr)

在此情况下,以下bash脚本的输出结果为:
OUTPUT=$(python /path/to/script.py)
echo $OUTPUT
for i in $OUTPUT;
do
    echo $i
done

is:

1 2 3
1
2
3

希望这能帮到您。

1
这是我见过的对这个“问题”最干净的解决方案之一。谢谢 - Václav
1
点赞,但更简单的方法是:print(" ".join(returnList)) - Anil

4

Bash声明数组的方式如下:

foo=(bar baz ban)

要将以空格分隔的命令输出转换为数组,您可以执行以下操作:

foo=($(my_command))

在Python中,将列表转换为以空格分隔的字符串非常容易:

' '.join(my_array)

如果你打印出来的是列表而不是列表本身,你因此可以轻松地将其转换为数组。


3
我会使用一个简短的Python包装器将字符串转换为更适合通过bash解析的内容。
# Proxy for script.py output that includes some potential bash pitfalls
python_output="['a b', 'c*', 6]"

# Let Python output each element of the list as a separate line;
# the only thing this cannot handle is multi-line elements; workarounds
# are possible, but not worth getting into unless necessary. 
while read -r; do
    OUTPUT+=("$REPLY")
done < <(python -c 'import ast, sys
print "\n".join(str(x) for x in ast.literal_eval(sys.argv[1]))
' "$python_output")

# Verify that each element was added to the array unscathed.
for e in "${OUTPUT[@]}"; do
    echo "$e"
done

在Bash 4中,您可以使用readarray命令替换while循环:
readarray -t OUTPUT < <(python -c ... )

1
如果你想在Python中从一个Python列表简单地创建一个Bash列表,你可以使用这个一行代码:
python -c 'print(" ".join([str(elem) for elem in [1, "l", 12]]))'

它直接给你列表:
1 l 12

请注意,这需要修改Python代码,而不是从外部Bash代码中执行此操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接