bash $ {VAR // search / replace}と奇妙な正規表現の動作


8

$ {VAR // search / replace}パラメータ展開を使用して、変数を検索および置換しようとしています。私はかなり長くて邪悪なPS1を持っているので、拡張後のサイズを計算します。そのためには、そこに詰め込んだ一連のエスケープシーケンスを削除する必要があります。ただし、すべてのANSI CSI SGRシーケンスを削除しようとすると、構文の問題に遭遇しました。

私のPS1を考えると:

PS1=\[\033]0;[\h] \w\007\]\[\033[1m\]\[\033[37m\](\[\033[m\]\[\033[35m\]\u@\[\033[m
\]\[\033[32m\]\h\[\033[1m\]\[\033[37m\]\[\033[1m\])\[\033[m\]-\[\033[1m\](\[\033[m
\]\t\[\033[37m\]\[\033[1m\])\[\033[m\]-\[\033[1m\](\[\033[m\]\[\033[36m\]\w\[\033[1m
\]\[\033[37m\])\[\033[35m\]${git_branch}\[\033[m\]\n$

(はい、それは私が知っている病気です...)

私がやろうとしていること:

# readability
search='\\\[\\033\[[0-9]*m\\\]'
# do the magic
sane="${PS1//$search/}"

しかし、これらは[0-9](ほとんどの[0-9]場合、.代わりにaのように扱われる)時点で貪欲であるようです:

echo "${PS1//$search/}"
\[\033]0;[\h] \w\007\]\n$ 

を削除して*に変更[0-9]すると[0-9][0-9](よりわかりやすくなります)、期待される結果に近づきます。

$ search='\\\[\\033\[[0-9][0-9]m\\\]'
$ echo "${PS1//$search/}"
\[\033]0;[\h] \w\007\]\[\033[1m\](\[\033[m\]\u@\[\033[m\]\h\[\033[1m
\]\[\033[1m\])\[\033[m\]-\[\033[1m\](\[\033[m\]\t\[\033[1m\])\[\033[m\]-\[\033[1m
\](\[\033[m\]\w\[\033[1m\])$(git_branch)\[\033[m\]\n$ 

なぜ*(ゼロ以上)クレイジーなことをしているのですか?ここで何か不足していますか?同じ正規表現をsedに渡すと、期待どおりの結果が得られます。

echo $PS1 | sed "s/$search//g"
\[\033]0;[\h] \w\007\](\u@\h)-(\t)-(\w)$(git_branch)\n$

3
これは正規表現ではなく、ファイルグロブに似た単なるパターンマッチングです。extglobパターンマッチングの動作には影響します。
ヨルダン2013

お尻、それが理由です-私はそれが事実であったかもしれない予感がありました:/私はあまり成功せずにマッチングメカニズムの明確化を見つけようとしました。extglobについて読むために向かいます(sedの仕事のように見えます!)
Drav Sloan 2013

1
*([0-9])[0-9]*使用するのと同じですextglob
ヨルダン2013

1
正解したら、自分の質問に答えてもかまいません。私はいくつかのガイダンスを提供できてうれしかったです。
ヨルダン2013

2
@DravSloan-このプロンプトは病気です!8
slm

回答:


6

\[との間にあるものを削除したいようです\]

$ shopt -s extglob
$ printf '%s\n' "${PS1//\\\[*(\\[^]]|[^\\])\\\]/}"
(\u@\h)-(\t)-(\w)${git_branch}\n$

ただし、bash置換は非常に効率が悪いため、おそらく発砲perlまたはsedここで実行するか、次のようなループで実行する方がよいでしょう。

p=$PS1 np=
while :; do
  case $p in
    (*\\\[*\\\]*) np=$np${p%%\\\[*};p=${p#*\\\]};;
    (*) break;;
  esac
done
np=$np$p
printf '%s\n' "$np"

(これは、上記の標準的なPOSIX sh構文です。BTW)。

そして、そこから拡張プロンプトが必要な場合:

ep=$(PS4=$np;exec 2>&1;set -x;:); ep=${ep%:}

4
ああ、私の一日は完了しました。コマンドラインの大祭司、ステファンからのより大きな年長の魔法のシ​​ンボルの別の束。私はあなたの投稿の半分を誓う私の目が間違ったボーレートに設定されていると私は混乱の画面を表示します:)そして、はい、最終的な目的はすべてのエスケープシーケンスを削除することでした:間[を削除するだけでは私を攻撃しませんでした]。ありがとう!
Drav Sloan 2013

5

jordanmからのガイダンス(およびbashのマニュアルページの「パターンマッチング」セクションを読んだ)の結果、パラメータ展開で使用されるこれらのパターンは正規表現ではないことがわかりました。ただし、私の特定のケースでshopt extglobは、オンの場合、次のことができます。

search='\\\[\\033\[*([0-9])m\\\]'

どこ*([0-9])と同じである[0-9]*正規表現では。

extglobは(bashのmanページから)正規表現に似たいくつかのメカニズムを提供しているようです。

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

2
はい、拡張グロブのextglobサブセットを実装しkshます。ksh93実際のパターンと(AT&T)のREの間で変換するためのprintf演算子を(持っているprintf '%P\n' '\\\[[0-9]*\\\]'与える*\\\[*([0-9])\\\]*
ステファンChazelas

うーん、* [0-9]は他の正規表現クエリで機能するようです(角括弧なし)。
macieksk

0

Pure BashでサポートされるANSIシーケンスの全範囲

# Strips ANSI CSI (ECMA-48, ISO 6429) codes from text
# Param:
# 1: The text
# Return:
# &1: The ANSI stripped text
strip_ansi() {
  echo -n "${1//$'\e'[@A-Z\[\\\]\^_]*([0-9:;<=>?])*([ \!\"#$%&\'()\^*+,\-.\/])[@A-Z\[\\\]\^_\`a-z\{|\}~]/}"
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.