1

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 }' アーマチュア)

そしてターミナルで配列を「エコー」します:

echo ${options[@]}

これは以下を示します:

「屋内用アーマチュア」 「屋内用照明」 「屋外用アーマチュア」 「屋外用照明」

これは 'whiptail' の選択メニューとして使用するのに問題ないように見えますが、そうではありません。コマンドライン:

whiptail --clear --title "アーマチュア" --menu "アーマチュアを選択" 50 80 10 ${options[@]}

ショー:

column1-column2

屋内アーマチュア

照明用

屋内用

屋外アーマチュア

照明用

屋外用

それ以外の:

column1-column2

屋内アーマチュア - 屋内用照明

屋外アーマチュア - 屋外用照明

'whiptail' では、二重引用符で囲まれた配列要素が無視されるか、表示されないようです。「${options[@]}」も試しましたが、常に最初の単語「Indoor」になります。

'whiptail' 以外に 'dialog' を試してみましたが、どちらも同じです。どちらの場合も、バージョン情報は 'cdialog (ComeOn Dialog!) version 1.1-20080316' と表示されます。

私はリソースが非常に限られているため、「xdialog」、「zenity」、「dzen」などに(まだ)冒険したくありません。たとえそれで問題が解決したとしてもです。また、XDSL (XBOX 用) のため、Linux 2.4.31 に制限されています。

私はインターネットをたくさん閲覧してきましたが、役に立ちませんでした。'whiptail/dialog' を使用した解決策は何ですか?

4

2 に答える 2

2

あなたが抱えている基本的な問題は、シェルがコマンドラインを解析する順序に起因します。変数をそれらの値に置き換える前に、引用符とエスケープを解析 (および削除) します。置き換えられた値。次の例を検討してください。

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

[ -n "$col1" ]更新:データベース ファイルの未終了の最終行に対してループを実行するテスト ( ) を追加しました。

二重引用符が実際にデータベース ファイルにある場合は、それらを削除する必要があります。これを処理する最も簡単な方法は、おそらく配列に文字列を追加するときに引用符を削除することです。配列を作成するときに文字列を置換する (「"」を空白に置き換える) bash の機能を使用します。

options=()
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
    options+=("${col1//'"'/}" "${col2//'"'/}")
done <armatures
于 2013-06-03T17:11:20.250 に答える
1

主な問題は、最初の回答で述べたように、bash (または他のシェル) がコマンドラインを「単語」に分割する方法にあります。行分割は、デフォルトで <space><tab><newline> に設定されている IFS (Internal Field Separator) に基づいて行われます。初期のシェルを開発した賢い男たち (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 のようなより原始的なシェルの場合は、"IFS=" (引用符なし) と入力して IFS を設定し、単一引用符を開き、<Enter> を押してから単一引用符で閉じる必要があります。再度リセットするには、"IFS=" (引用符なし) と入力し、一重引用符を開き、<スペース> を入力し、(Ctrl-V などで) <tab> を引用し、<Enter> を押してから一重引用符で閉じます。

于 2016-01-30T02:08:25.253 に答える