whiptail / dialog菜单项中的bash空格

时间:2013-06-03 13:18:25

标签: bash dialog dsl xbox whiptail

我想用bash-dialog创建一个简单的对话框。我使用(X)DSL和bash-3.2。最新的(X)DSL基于Linux 2.4.31并附带bash-2.05,但是,bash-3.2可以从MyDSL / Testing下载。所以,我的脚本运行在'#!/ bin / bash-3.2 / bin / bash'。

用户可以选择的菜单项来自数据库。

示例数据库文件'示例':

  

室内照明|室内照明

     

户外照明|户外照明

我将数据检索到数组'选项'来自'电枢'文件:

  

options =($(awk -F" |"' {print $ 1,$ 2}' armatures)

并在终端' echo'数组:

  

echo $ {options [@]}

显示:

  

"室内电枢" "室内照明" "户外电枢" "户外照明"

这看起来可以用作带有' whiptail'的选择菜单。但它不是。命令行:

  

whiptail --clear --title" Armatures" --menu"选择一个电枢" 50 80 10 $ {options [@]}

所示:

  

列1-COLUMN2

     

室内-电枢

     

照明为

     

室内用途

     

室外-电枢

     

照明为

     

户外用途

代替:

  

列1-COLUMN2

     

室内电枢 - 室内照明

     

户外电枢 - 户外用品

似乎带有双引号的数组元素被忽略或未被' whiptail'看到。我也试过" $ {options [@]}"但这总是会产生第一个词'室内'

除了' whiptail'我试过对话'但它们是相同的:版本信息显示&#cd; cd(ComeOn Dialog!)版本1.1-20080316'在这两种情况下。

我的资源非常有限,并且不想冒险进入' xdialog' zenity'' dzen'等等,即使这样可以解决这个问题。由于XDSL(对于XBOX),我也仅限于Linux 2.4.31。

我一直在浏览互联网,但无济于事。使用' whiptail / dialog'

可以解决什么问题

2 个答案:

答案 0 :(得分:1)

你遇到的基本问题来自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变量具有高度误导性;如果它表明看起来像是正确的引用,那实际上意味着有一些可怕的错误,因为它应该在引用删除后显示参数

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

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

更新:我添加了一个测试([ -n "$col1" ])来执行数据库文件中未终止的最后一行的循环。

如果双引号实际上在数据库文件中,则必须将其删除;最简单的处理方法可能是在将字符串添加到数组时删除引号,使用bash的字符串替换功能(在构建数组时用空格替换“”):

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

答案 1 :(得分:0)

主要问题是bash(或任何其他shell)将命令行分成“单词”的方式,如第一个答案中所述。线分割是在IFS - 内部场分离器的基础上完成的,其设置为&lt; space&gt;&lt; tab&gt;&lt; newline&gt;默认情况下。开发早期炮弹的聪明人(Stephen Bourne等)显然认为用户能够改变它是一个好主意。它也可以设置为多字符值。

所以你真正需要做的就是将字段分隔符设置为换行符,运行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 =”(不带引号),打开单引号,按&lt; Enter&gt;,然后用单引号关闭来设置IFS。要重新设置,请输入“IFS =”(不带引号),打开单引号,输入&lt; space&gt;,引号(例如Ctrl-V)a&lt; tab&gt ;,点击&lt; Enter&gt;,然后关闭单引号。