web-dev-qa-db-ja.com

正規表現(bash)を使用したシェル変数の変更

たとえば、Shell変数があります。 a = "大きな小さな男"。 bashで正規表現を使用して変数を真ん中の単語だけを大文字にして出力するにはどうすればよいですか? (大きな小さな男)

変数を3つの変数に分離し、それらをエコーで展開することでそれを行うことができます。たとえばfirst=${a%* }など。しかし、1つの正規表現で1つのシングルゴーにするにはどうすればよいですか。

一行でそれを行うことは可能ですか?大文字の演算子を使用する(^)

1
Vaish MK

sed

GNU sed:を使用していると仮定します。

$ sed -E 's/(\w+) (\w+) (\w+)/\1 \U\2\E \3/' <<< 'big little man'
big LITTLE man

このコマンドは、 GNU固有のシーケンス\Uおよび\Eを使用して、後続の文字をそれぞれ大文字に変換し、大文字と小文字の変換をキャンセルします。

awk

正規表現を操作していませんが、awkは、単一の単語を大文字にする別の便利な方法を提供します。

$ awk '{print($1, toupper($2), $3)}' <<< 'big little man'
big LITTLE man

bash

Bash自体には正規表現ベースの変換はありませんが、文字列を配列として扱うことで部分大文字化を実現できます。

$ (read -a words; echo "${words[0]} ${words[1]^^} ${words[2]}") <<< 'big little man'
big LITTLE man

ここで、^^は、配列の2番目の要素(つまり、2番目のWord)を大文字に変換します。この機能はBash 4で導入されました。

bash拡張演算子で一度に実行できるとは思いません。 zshでできます:

_set -o extendedglob # for (#m)

b=${a/(#m) * /${(U)MATCH}}
_

または:

_b=${(S)a/(#b)(*) (*) (*)/$match[1] ${(U)match[2]} $match[3]}
_

どこ:

  • _(#m)_により、一致した文字列が_$MATCH_で使用可能になります
  • _(#b)_は後方参照を有効にします
  • ${(U)var}(また__$var:u_)は大文字になります(bashの_${var^^pattern}_より数十年前)。
  • _(S)_は貪欲でないマッチングをオンにします。
0

リクエストに応じて、${variable^^}を使用してbashで1行に実行します。

$ a="big little man"
$ [[ "$a" =~ ^([^ ]+)\ ([^ ]+)\ (.*) ]] && a="${BASH_REMATCH[1]} ${BASH_REMATCH[2]^^} ${BASH_REMATCH[3]}"
$ echo "$a"
big LITTLE man

これは、正規表現([^ ]+)\ ([^ ]+)\ (.*)$aの文字列と照合します。一致する場合は、スペースで区切られた3つのサブストリングが含まれます。最初と2番目の部分文字列はスペースを含まない任意の文字列であり、3番目の部分文字列は文字列の残りのビットになります。

式が一致した場合、$aの値は、大文字の2番目の部分文字列で書き換えられます。

これは、元の文字列がスペース以外の文字で始まることを前提としています。

0
Kusalananda