循环遍历 python 脚本的输出时,bash 中的“echo”出现问题

循环遍历 python 脚本的输出时,bash 中的“echo”出现问题

给定 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中使用的提示符。默认值后跟一个空格。selectbash#?

答案2

看起来像declare -a choice=$( python3 test.py )制作一个 1 长度的数组,其中

choice[0]='first
second
third'

尝试declare -a choice=( $( python3 test.py ) )

相关内容