変数から部分文字列を置き換えるにはどうすればいいですか?

変数から部分文字列を置き換えるにはどうすればいいですか?

文字列変数から文字を削除しようとしています。sed次のようにすればうまくいきます:

MYVAR=--23ho02123ware38384you443d34o3434ingtod38384day-%§*#sfrf
echo ${MYVAR} | sed -e 's/[a-z][a-z0-9\-]*//g'

そして次のようになります:

 --23%§*#

それが私が探しているものです。文字列は文字で始まり、文字、数字、ダッシュ (-) のみで構成されている必要があります。bash文字列置換でこれを実現する方法はありますか?

MYVAR=${MYVAR/[a-z][a-z0-9-]*/ }

いくつかの組み合わせを試してみましたが、どれも期待通りには機能しませんでした。

答え1

正規表現と同等のものを得るには、ksh 拡張 glob 演算子 (そのサブセットはbashwithshopt -s extglobおよびzshwithで使用可能) を使用する必要があります (ただし、構文は異なります。ここではと同等のものは次のようになります)。set -o kshglob*(x)x*

shopt -s extglob # for bash
# set -o kshglob # for zsh
printf '%s\n' "${MYVAR//[[:alpha:]]*([[:alnum:]-])/}"

または、zsh extendedglobs の場合、 regexp と同等のものは次のように*なります#

set -o extendedglob
printf '%s\n' ${MYVAR//[[:alpha:]][[:alnum:]-]#}

いくつかの注意事項:

  • ${var/pattern/replacement}最初の出現のみを置き換えます。すべての出現を置き換えるには、 を使用します(のコマンドのフラグ${var//pattern/replacement}と同様)。gseds
  • 置換文字をスペース文字にした場合、空の文字列に置き換えるには${var//pattern/}(または) を使用します。${var//pattern}
  • echo任意の文字列を出力するために使用したくない
  • ただしzshリストコンテキストでの変数展開は引用符で囲む必要がある
  • sed変数に改行文字が含まれている場合、動作はあなたのアプローチとは異なります。
  • [a-z]aは、との間の文字(一部のツールでは照合要素)に一致します。zこの文字のリストは、ロケール、システム、ツールによって異なります(たとえば、GNUシステムのロケールで[a-z]は、、、に一致しますが、 には一致しません)。これには通常、英語のアルファベットの26個の小文字が含まれますが、必ずしもそうとは限りません。には、 と見なされる文字(または照合要素)が含まれます。bash-4.3en_GB.UTF-8AXéZ[[:alpha:]]アルファベット順(大文字と小文字を区別しない) をロケールで使用します。26 個の英語の文字のみを一致させたい場合は、[abcdefghijklmnopqrstuvwxyz]ロケールをC( LC_ALL=C) に固定し、小文字の英語の文字のみに[a-z]または を使用し、すべての英語の文字に/ を使用します。[[:lower:]][a-zA-Z][[:alpha:]]
  • [a-z0-9\-]sedバックスラッシュ文字と一致しないため、[a-z0-9-]代わりに を使用します (-文字どおりに解釈されるためには、 が最初または最後にある必要があります)。

関連情報