Bashプロンプトの関数で非印刷文字をエスケープする


22

Bashプロンプト(PS1変数)で、潜在的にプロンプ​​トにテキストを追加する関数を呼び出しています。 export PS1="\u@\h \$(my_function) \$ "

ただし、プロンプト内の関数には、関数の出力に基づいて変化するANSIカラーコードが含まれています(赤、場合によっては緑)。\[PS1変数に「」を追加すると、これらのコードが非印刷としてエスケープされるはずですechoが、関数で「\[」を実行すると、「」が文字通りプロンプトに印刷されます。

bashプロンプトで使用するために、これらのANSIカラーコードを関数内からエスケープするにはどうすればよいですか?

回答:


34

readlineのライブラリーは、受け入れ\001\002(ASCII SOHとSTX非印刷可能なテキストの区切り文字として)。これらはreadlineを使用するアプリケーションでも機能します。

からlib/readline/display.c:243bashのソースコード:

243 /* Current implementation:
244         \001 (^A) start non-visible characters
245         \002 (^B) end non-visible characters
246    all characters except \001 and \002 (following a \001) are copied to
247    the returned string; all characters except those between \001 and
248    \002 are assumed to be `visible'. */

バッシュ固有\[\]実際にに翻訳されている\001\002y.tab.c:7640


注:あなたが使用している場合はbashをprintfecho -e、そして、あなたのテキストがある場合\001\002、すぐに番号の前に、あなたがヒットよ、bashの進エスケープを処理するとき、それはあまりにも多くの一桁を食べるようになり、バグを- 、される\00142進として解釈されます014(ASCII "2"が続く)、正しい8進数01(ASCII "42"が続く)の代わりに。このため、代わりに16進バージョン\x01\x02使用してください。


できた!echo -e "\001\e[31m\002RED"期待どおりに動作します。ありがとう!
MidnightLightning

回答を復活させて申し訳ありませんが、dash / ash / shで同等のものは何ですか?
ホシュサディク

@Hosh彼らはreadlineを使用し、場合\001\002動作します。それ以外の場合はわかりません。たとえば、ダッシュは間違いなくreadlineを使用しません
wjandrea

1

ここに完全な答えがあります。\ 001などがどこに行かなければならないかを知るために、私はもっと掘り下げなければなりませんでした。お役に立てれば。

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

ここで設定した方法は、gitブランチにいる場合にのみgitブランチの括弧が表示されます。それ以外の場合は空白です。


0

基づいてgrawityの回答、以下はASCIIでANSI制御配列を同封しますSOH^A)とSTX^B)と同等である\[\]、それぞれ:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

次のように使用します。

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

または:

$ readline_ANSI_escape "$string"

ボーナスとして、関数を複数回実行しても、すでにエスケープされた制御コードが再エスケープされません。


-2

プロンプトでそれらを使用する場合、を実行する必要があり\[ます。ただし、エコーで使用する場合は、を使用する必要があります\033[


うーん... ANSIコマンドの前に\ 033 [( "\ e [31m")と\ 033]を追加すると、プロンプトで次の印刷文字が印刷されないように見えます。
MidnightLightning

1
その後に\ 033]をしたくありません。\ 033 [31mは色を開始します。その後、\ 033 [0m
Wuffers
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.