whiptail/对话框菜单项中的bash空格

whiptail/对话框菜单项中的bash空格,bash,dialog,dsl,xbox,whiptail,Bash,Dialog,Dsl,Xbox,Whiptail,我想用bash对话框创建一个简单的对话框。我使用(X)DSL和bash-3.2。最新的(X)DSL基于Linux2.4.31,并随bash-2.05一起提供,但是,bash-3.2可以从MyDSL/Testing下载。所以,我的脚本在“#”下运行/bin/bash-3.2/bin/bash' 用户可以从数据库中选择菜单项 示例数据库文件“armatures”: 室内照明|室内使用照明 室外照明|室外使用照明 我从“电枢”文件中将数据检索到一个数组“选项”,其中包含: 选项=($(awk-F“|”

我想用bash对话框创建一个简单的对话框。我使用(X)DSL和bash-3.2。最新的(X)DSL基于Linux2.4.31,并随bash-2.05一起提供,但是,bash-3.2可以从MyDSL/Testing下载。所以,我的脚本在“#”下运行/bin/bash-3.2/bin/bash'

用户可以从数据库中选择菜单项

示例数据库文件“armatures”:

室内照明|室内使用照明

室外照明|室外使用照明

我从“电枢”文件中将数据检索到一个数组“选项”,其中包含:

选项=($(awk-F“|”{打印$1,$2}”电枢)

在终端“回声”阵列中:

options=()
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
    options+=("${col1//'"'/}" "${col2//'"'/}")
done <armatures
echo${options[@]}

这表明:

“室内电枢”“室内照明”“室外电枢”“室外照明”

这看起来可以用作带有“whiptail”的选择菜单,但实际上不行。命令行:

鞭梢--清除--标题“电枢”--菜单“选择电枢”50 80 10${选项[@]}

显示:

第1-2栏

室内电枢

照明

室内使用

户外电枢

照明

户外使用

代替:

第1-2栏

室内用室内电枢照明

户外用电枢灯

“whiptail”似乎忽略了或看不到带双引号的数组元素。我也尝试了“${options[@]}”,但结果总是出现在第一个单词“indior”上

除了“whiptail”之外,我尝试了“dialog”,但它们是一样的:在这两种情况下,版本信息都显示“cdialog(ComeOn dialog!)版本1.1-20080316”

我的资源非常有限,不想(现在)冒险使用“xdialog”、“zenity”、“dzen”之类的东西,即使这样可以解决这个问题。由于XDSL(用于XBOX),我也只能使用Linux 2.4.31


我经常浏览互联网,但都没用。“whiptail/dialog”的解决方案是什么?

您遇到的基本问题来自shell解析命令行的顺序:它解析(并删除)在用变量替换变量之前引用和逃逸,并且对于替换的值中的任何引号或逃逸都不会返回和重新解析。
var='"foo bar"'   # Note that the single-quotes will be removed, and the
                  # double-quotes will be treated as part of the variable value.
somecmd $var   # This runs cmd with 2 arguments: '"foo' and 'bar"'
在您的情况下,我不确定双引号来自何处;它们不在您提供的文件列表中,awk命令不会添加它们。但在任何情况下,您都不希望它们存储为值的一部分,而是希望它们围绕变量引用:

var='foo bar'   # Again, the single-quotes are removed.
somecmd "$var"   # This runs cmd with a single argument: 'foo bar'
由于您使用的是数组,所以您的情况稍微复杂一些,但同样的原则也适用。请注意,
echo
ing一个变量具有高度误导性;如果它显示的是正确的引号,则实际上意味着存在严重错误,因为它应该在删除引号后显示参数

那么,你如何解决它呢?试试这个:

options=()
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
    options+=("$col1" "$col2")  # Note the double-quotes around the variable references
done <armatures
echo "options:"
printf "  '$s'\n" "${options[@]}"  # This prints each array element on a separate line
whiptail --clear --title "Armatures" --menu "Choose an armature" 50 80 10 "${options[@]}"  # Again, double-quotes around the reference

主要问题在于bash(或任何其他shell)将命令行拆分为“单词”的方式,如第一个答案中所述。行拆分基于默认设置为的IFS(内部字段分隔符)。聪明的chaps(Stephen Bourne等)开发早期Shell的人显然认为用户可以更改它是个好主意。它还可以设置为多字符值

因此,您真正需要做的就是将字段分隔符设置为换行符,运行awk脚本,然后将其设置回原来的位置。在使用数组时,还应该引用它

这应该适用于bash:

IFS=$'\n'
options=($(awk -F"|" '{ print $1,$2 }' armatures)
IFS=$' \t\n'
数组成员现在已正确定义。然后:

whiptail --clear --title "Armatures" --menu "Choose an armature" 50 80 10 "${options[@]}"

对于像Bourne Shell这样的基本Shell,您可能需要通过输入“IFS=”(不带引号),打开单引号,按,然后用单引号结束来设置IFS。要再次重置它,请输入“IFS=”(不带引号),打开单引号,输入引号(例如Ctrl-V)a,点击,然后用一个引号结束。

谢谢!Shell解析不容易理解,但您的解释帮助很大。但是您建议的代码有一个问题:最后一条记录没有显示在“whiptail”中,即在上面的示例中,只显示第一条记录。通过添加一条额外的记录,只显示“|”,两条记录都显示在“whiptail”中。如何避免添加额外的“|”记录?@linuph:数据库中的最后一行可能未终止(即结尾没有换行符);我添加了一个测试来运行任何非空行的循环,即使它没有终止。顺便说一句,这表明数据库文件不是标准的unix文本文件格式,可能是DOS格式,在这种情况下,它将在每一行的末尾有一个非打印的回车字符(它将在每个col2条目的末尾结束)。如果是这样,有一些方法可以过滤它…我在数据库中没有双引号,所以没关系。我将检查最后一行的终止。再次感谢!确实,为了避免丢失最后一条记录,最后一条记录必须用下一行代码终止,即“\n”。仅此而已。