変数内の特定の単語を削除する

変数内の特定の単語を削除する

スクリプトではbash、文字列から単語を削除するにはどうすればよいですか。単語は変数に格納されます。

FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"

答え1

部分文字列置換の使用bash(ksh93 からコピー):

FOO=${FOO//"$WORDTOREMOVE"/}

//は、部分文字列 ( ) のすべての出現をと$WORDTOREMOVEの間の内容に置き換えます。この場合は何も起こりません。/}

$WORDTOREMOVE内容がパターンではなく固定文字列として扱われるように、引用符で囲むことに注意してください。

置換が空の場合は、 を/省略することもできます${FOO//"$WORDTOREMOVE"}

これとbashで文字列を操作する他の方法については、セクションを参照してください。10.1. 文字列の操作高度な Bash スクリプト ガイド

答え2

試す:

$ printf '%s\n' "${FOO//"$WORDTOREMOVE"/}"
CATS DOGS FISH

ksh93これは、(それが由来するところ)でも機能しmkshますzsh


POSIXLy: 正:

FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"

remove_word() (
  set -f
  IFS=' '

  s=$1
  w=$2

  set -- $1
  for arg do
    shift
    [ "$arg" = "$w" ] && continue
    set -- "$@" "$arg"
  done

  printf '%s\n' "$*"
)

remove_word "$FOO" "$WORDTOREMOVE"

単語がスペースで区切られていると想定し、前後のスペースを削除する副作用があります"$WORDTOREMOVE"

答え3

使用できますsedこのような:

echo $FOO | sed s/"$WORDTOREMOVE"//

答え4

1つ削除言葉空白で区切られた単語リストを表す文字列から、各側のスペースをどうするかを決める必要があるため、これはそれほど簡単ではありません。

単語間に常に 1 つのスペースがある、制御された表現の場合でも、いくつかの異なるケースを区別する必要があります。

  • 真ん中の単語: foo MICE bar-> foo bar: 単語とその前後のスペースが 1 つのスペースに置き換えられます。${var/+( )MICE+( )/ }
  • 先頭の単語: MICE foo bar-> foo bar: 単語とその後のスペースは何も置換されません:${var/MICE+( )}
  • 末尾の単語: foo bar MICE-> foo bar: 単語とその前のスペースは何もないものに置き換えられます: ${var/+( )MICE}.
  • 次に、where という単語が連続して複数出現すると、最初の置換によって 2 番目の MICE の前のスペースが消費されるため、${var// MICE / }機能しないという問題があります。foo MICE MICE bar

(上記は${var/pattern/replacement}ksh93 の演算子を使用しています)。

ただし、置換を行う前に先頭と末尾にスペースを追加し、置換後にスペースを削除すると、1 つの置換演算子ですべての範囲をカバーできるため、作業が簡単になります。

var='MICE foo MICE MICE bar MICE'
word=MICE

var=" $var "
var=${var//+(+([[:space:]])"$word")+([[:space:]])/ }
var=${var# } var=${var% }

1 つ以上の空白文字に一致する ksh88 演算子をサポートするには、事前にshopt -s extglobbash またはset -o kshglobzsh で必要になります。+([[:space:]])

または、zshの独自のextendedglobs ( set -o extendedglob) を使用すると、ksh の は次のよう+(x)になりますx##

var=${var//([[:space:]]##$word)##[[:space:]]##/ }

単語の前後にあったスペースを ( zsh; ksh93 には同等のものがありますが、bash にはありません) で復元することも可能です。

var='MICE foo MICE MICE bar MICE'
word=MICE

set -o extendedglob
var=" $var "
var=${var//(#b)([[:space:]]##$word)##([[:space:]]##)/$match[2]}
var=${var# } var=${var% }

リストの表現を含むスカラー変数の代わりに、実際のリスト(配列) 変数、例:

var=(MICE foo MICE MICE bar MICE)

すると、問題は配列から特定の要素を削除することに集約され、次のような適切な配列変数を持つシェルを使用すると簡単になりますzsh(このvar=(foo bar)構文の由来は次のとおりです)。

var=( ${var:#$word} )

関連情報