70

PS1色を動的に選択するようにプロンプ​​ト変数を設定しようとしています。これを行うために、色名を使用して一連のローカル変数を定義しました。

$ echo $Green
\033[0;32m

しかし、変数を動的に割り当てる際にそれらを使用したいと思っていましたが、それらを適切に拡張する方法がわかりません。

> colorstr="\${$color}"
> echo $colorstr
${Green}

eval、、echoおよび二重引用符の組み合わせを12回試しましたが、どれも機能しないようです。変数を展開する論理的な方法(私は思った)はエラーになります:

> colorstr="${$color}"
-bash: ${$color}: bad substitution

(わかりやすくするために、プロンプト文字の>代わりに使用しまし$たが、bashを使用しています)

その変数を展開するにはどうすればよいですか?つまり、どういうわけか「緑」という単語を値に変換します\033[0;32mか?そして、できれば、bashまたは端末にそれ\033[0;32mを緑色として解析させることもできます。

編集:私は誤用し${!x}eval echo $xいたので、以前はそれらを解決策として受け入れました。(おそらく病的に)好奇心旺盛な人のために、関数とPS1変数はこの要点にあります:https ://gist.github.com/4383597

4

5 に答える 5

79

使用evalは古典的な解決策ですがbash、より優れた(より簡単に制御でき、大失敗のようなものではない)解決策があります。

  • ${!colour}

Bash(4.1)リファレンスマニュアルには次のように書かれています。

パラメーターの最初の文字が感嘆符(!)の場合、可変間接レベルのレベルが導入されます。Bashは、残りのパラメーターから形成された変数の値を変数の名前として使用します。次に、この変数が展開され、パラメーター自体の値ではなく、その値が残りの置換で使用されます。これは、間接拡張として知られています。

例えば:

$ Green=$'\033[32;m'
$ echo "$Green" | odx
0x0000: 1B 5B 33 32 3B 6D 0A                              .[32;m.
0x0007:
$ colour=Green
$ echo $colour
Green
$ echo ${!colour} | odx
0x0000: 1B 5B 33 32 3B 6D 0A                              .[32;m.
0x0007:
$

(このodxコマンドは非常に非標準ですが、データを16進形式でダンプし、右側に印刷可能な文字を表示します。プレーンechoには何も表示されず、エコーされているものを確認する必要があるため、私が書いた古い友人を使用しました。約24年前。)

于 2012-12-27T06:09:16.697 に答える
20

evalを使用すると次のようになります。

green="\033[0;32m"
colorstr="green"
eval echo -e "\$$colorstr" test           # -e = enable backslash escapes
test

最後のテストは緑色です。

于 2012-12-27T03:55:23.400 に答える
1

Bashは連想配列をサポートしています。dictを使用できる場合は、間接参照を使用しないでください。連想配列がない場合は、bash 4、ksh93、またはzshにアップグレードしてください。どうやらmkshは最終的にもそれらを追加しているので、たくさんの選択肢があるはずです。

function colorSet {
    typeset -a \
        clrs=(black red green orange blue magenta cyan grey darkgrey ltred ltgreen yellow ltblue ltmagenta ltcyan white) \
        msc=(sgr0 bold dim smul blink rev invis)

    typeset x

    while ! ${2:+false}; do
        case ${1#--} in
            setaf|setab)
                for x in "${!clrs[@]}"; do
                    eval "$2"'[${clrs[x]}]=$(tput "${1#--}" "$x")'
                done
                ;;
            misc)
                for x in "${msc[@]}"; do
                    eval "$2"'[$x]=$(tput "$x")'
                done
                ;;
            *)
                return 1
        esac
        shift 2        
    done
}

function main {
    typeset -A fgColors bgColors miscEscapes
    if colorSet --setaf fgColors --setab bgColors --misc miscEscapes; then
        if [[ -n ${1:+${fgColors[$1]:+_}} ]]; then
            printf '%s%s%s\n' "${fgColors[${1}]}" "this text is ${1}" "${miscEscapes[sgr0]}"
        else
            printf '%s, %s\n' "${1:-Empty}" 'no such color.' >&2
            return 1
        fi
    else
        echo 'Failed setting color arrays.' >&2
        return 1
    fi
}

main "$@"

を使用していますがeval、別の理由で別のタイプの間接参照です。これを安全にするために必要なすべての保証がどのように行われるかに注意してください。

参照:http://mywiki.wooledge.org/BashFAQ/006

于 2012-12-29T01:16:41.247 に答える
0

関数のエイリアスを作成する必要があります。http://tldp.org/LDP/abs/html/functions.html、まともな小さなチュートリアルといくつかの例をチェックしてください。

編集:申し訳ありませんが、私は問題を誤解したようです。まず、変数の使用が間違っているようです。http://www.thegeekstuff.com/2010/07/bash-string-manipulation/を確認してください。また、このスクリプトを呼び出すものは何ですか?これを.bash_profileに追加しますか、それともユーザーが起動できるスクリプトですか?エクスポートを使用すると、再ログを必要とせずに変更をすぐに有効にする必要があります。

var Green="\[\e[32m\]"
var Red="\[\e41m\]"

export PS1="${Green} welcome ${Red} user>"
于 2012-12-27T03:47:15.340 に答える
0

最初の結果は問題を示しています:

$ echo $Green
\033[0;32m

変数Greenには、。の文字列が含まれていますa backlash, a zero, a 3, etc.

それはによって設定されました:Green="\033[0;32m"。そのため、カラーコードではありません。
変数内のテキストを解釈する必要があります(echo -e、printf、または$'...'を使用)。

コードで説明しましょう:

$ Green="\033[0;32m"    ;     echo "  $Green   test   "
  \033[0;32m   test     

あなたがすることを意味することは次のとおりです:

$  Green="$(echo -e "\033[0;32m" )"    ;     echo "  $Green   test   "
 test   

素晴らしい色の緑。これは色を印刷する可能性がありますが、PS1には役立ちません。

$  Green="\033[0;32m"    ;     echo -e "  $Green   test   "
 test   

文字列が機能する前に、文字列を解釈する必要があることを意味しますecho -e

(bashでの)より簡単な方法は次のとおりです。

$ Green=$'\033[0;32m'    ;     echo "  $Green   test   "
  test   

注意してください` $'...' `

変数の問題を解決した後Green、var colorstrの値によって間接的にアクセスすることは、次のいずれかによって解決できる2番目の問題です。

$ eval echo \$$colorstr testing colors
testing colors
$ echo ${!colorstr} testing colors
testing colors

一般に、引用符で囲まれていない値(値は自分で管理しているため、ここで行ったように)を使用しないでください。次のように、正しく引用することを学びます。

$ eval echo \"\$$colorstr testing colors\"

これで、次のようなPS1を作成できます。

export PS1="${Green} welcome ${Red} user>"

と:

Green=$'\033[0;32m'    Red=$'\033[0;31m'
color1=Green           color2=Red
export PS1="${!color1} welcome ${!color2} user>"
于 2015-12-17T06:51:16.853 に答える