1

次のような文字列が与えられた場合

string="val1 val2 val3 val4"

bash 部分文字列置換を使用して、特定の部分文字列とそれに隣接するスペース (存在する場合と存在しない場合があります) を削除するにはどうすればよいですか?

たとえば、これにより余分なスペースが発生します。

val='val2'
string=${string/$val/}
# string = "val1  val3 val4"

私の実際のコードでは、部分文字列が何であるか、または文字列内のどこにあるかを事前に知ることはできないため、先頭または末尾にスペースがあるかどうかは不明です。で行うように、次のようなことをしたかったのですsedが、もちろんうまくいきませんでした。

val=" *val2 *"
string=${string/$val/ }
# In my fictitious universe, string = "val1 val3 val4"
# In the real world, string = "val1"

ではsed、 のようなものを使用しますsed -e 's/ *val2 */ /'が、これらすべてを bash 内から実行したいと考えています。

パターンに 0 個以上のスペース + 'val2' + 0 個以上のスペースが含まれるように部分文字列を定義する方法はありますか?

4

2 に答える 2

4

仕様の問題

初期状態として考えてみましょう:

v=val2
string="val1 val21 val2 val3 val4"

この質問が求める正確な動作を実装すると、次のようになります。

string="val1 1 val3 val4"

...多分:

string="val1 1 val2 val3 val4"

以下では、この場合の出力として本当に必要なものは次のとおりであると想定しています。

string="val1 val21 val3 val4"

アプローチ: Posix 拡張正規表現 / BASH_REMATCH

これは厳密に必要というよりも複雑です (当面のケースでは、この下に示す別のアプローチを使用します) が、ネイティブ bash で文字列を置換するための正規表現の使用を示しています。これは、多くの場合、便利な手法です。

を使用することを検討してください。これは、正規表現からのグループを[[ $string =~ $re ]]配列に取り込みます。BASH_REMATCHre

string="val1 val2 val3 val4"
val=val2

if [[ $string =~ (.*(^|[[:space:]]))"$val"(($|[[:space:]]).*) ]]; then
  string="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
  string=${string//  / } # deal with any places where spaces are doubled up
fi

一時パディングによるパターン置換

無条件に文字列の先頭と末尾にスペースを追加すると、正規表現のような条件なしで、文字列内の任意の場所にある値を削除して、同一の置換ロジックを使用できることを意味します。

string="val1 val2 val3 val4"
val=val2

s=" $string "       # Unconditionally add leading and trailing spaces
s=${s// $val / }    # Substitute the value only when surrounded by space
s=${s# }; s=${s% }  # Trim leading and trailing spaces back off

string=$s
于 2016-08-17T02:09:07.483 に答える
3

提供さextglobれたシェル オプションが有効になっている場合、

$ string="val1 val2 val3 val4"
$ v=val2
$ echo "${string/*( )$v*( )/ }"
val1 val3 val4
  • string/パターンの最初の出現を検索して置換するために使用されます。string//すべてのオカレンスを置き換えるために使用します。詳細については、パラメータ展開を参照してください
  • *( )0 個以上のスペースを意味します。オプションの詳細と使用方法については、パターン マッチングのマニュアルを参照してください。extglob
  • 置換パターンは単一のスペース文字です
于 2016-08-17T01:20:28.193 に答える