我想用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'
可以解决什么问题答案 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;,然后关闭单引号。