![循环遍历 python 脚本的输出时,bash 中的“echo”出现问题](https://linux22.com/image/157965/%E5%BE%AA%E7%8E%AF%E9%81%8D%E5%8E%86%20python%20%E8%84%9A%E6%9C%AC%E7%9A%84%E8%BE%93%E5%87%BA%E6%97%B6%EF%BC%8Cbash%20%E4%B8%AD%E7%9A%84%E2%80%9Cecho%E2%80%9D%E5%87%BA%E7%8E%B0%E9%97%AE%E9%A2%98.png)
给定 python 脚本
if __name__ == '__main__':
print("first")
print("second")
print("third")
bash 脚本
#!/usr/bin/env bash
declare -a choice=$( python3 test.py )
echo "You chose "
for c in "${choice[@]}"; do
echo "> ${c}"
done
应该打印
You chose
> first
> second
> third
但相反,它打印
You chose
> first
second
third
为什么会这样,我该如何解决这个问题?
答案1
Python 脚本打印三行文本。要将它们读入数组中bash
,请使用readarray
:
readarray -t chose < <( python3 test.py )
printf '> %s\n' "${chose[@]}"
该readarray -t
命令将从标准输入读取行到给定的数组中。使用进程替换从 Python 脚本重定向标准输入。默认情况下,实用readarray
程序将读取单独的行,即以换行符结尾的文本字符串,并且该-t
选项使实用程序从读取的数据中删除终止换行符。
该printf
调用打印每个数组元素,并带有前导>
和空格。向 提供多个参数printf
(通过向其提供像这样的数组扩展来实现),它将重用其格式化字符串来输出每个单独的参数。这意味着不需要循环。
您的脚本的问题在于您正在将 Python 脚本的输出读入单个字符串。命令替换$( python3 test.py )
将扩展为一个字符串,然后您必须手动解析该字符串并将换行符拆分为正确的数组元素。
你可以做正如达轰炸机建议的那样并让 shell 为您执行此拆分choice=( $( python test.py ) )
(不需要declare -a
),但请注意,这会将字符串拆分为任何空白(默认情况下是空格、制表符和换行符( 的内容$IFS
)),如果您希望各个数组元素包含空格,这可能不是您想要的。
那么一个选项可能是设置IFS
为换行符以使 shell 在换行符上分割数据仅有的,或者使用 、 读取 Python 代码的输出read
,这些可能是很好的解决方案,但您有readarray
内置实用程序bash
可以使这变得更容易。
看起来(从代码中的变量名称和其他文本来看)您可能想要实现某种交互式菜单。
select
这也可以通过以下方式完成bash
:
readarray -t options < <( python3 test.py )
echo 'Please select your option' >&2
PS3='Your selection: '
select ch in "${options[@]}"; do
[ -n "$ch" ] && break
echo 'Invalid, try again' >&2
done
printf 'You chose option %d ("%s")\n' "$REPLY" "$ch"
这将使用 Python 脚本的输出作为select
循环中的选项。循环将继续,直到用户选择了有效选项。最后,打印所选选项(及其编号)。
该提示符是inPS3
中使用的提示符。默认值后跟一个空格。select
bash
#?
答案2
看起来像declare -a choice=$( python3 test.py )
制作一个 1 长度的数组,其中
choice[0]='first
second
third'
尝试declare -a choice=( $( python3 test.py ) )