10

私はぎこちない初心者なので、ご容赦ください。

目標は、すべての単語の最初の文字が大文字で残りの文字が小文字になるように、文字列の大文字と小文字を変更することです。(例を単純にするために、ここでは「単語」は厳密にアルファベット文字として定義されています。その他はすべて区切り文字と見なされます。)

次の awk コマンドを使用して、この Web サイトの別の投稿から、すべての単語の最初の文字を大文字にする良い方法を学びました。

echo 'abce efgh ijkl mnop' | awk '{for (i=1;i <= NF;i++) {sub(".",substr(toupper($i),1,1),$i)} print}' --> Abcd Efgh Ijkl Mnop

残りの文字を小文字にするには、awk コマンドの前に tr コマンドを付けることで簡単に実行できます。

echo 'aBcD EfGh ijkl MNOP' | tr [A-Z] [a-z] | awk '{for (i=1;i <= NF;i++) {sub(".",substr(toupper($i),1,1),$i)} print}' --> Abcd Efgh Ijkl Mnop

ただし、awk についてさらに学習するために、同様の awk コンストラクトを使用して、最初の文字を除くすべての文字を小文字に変更したいと考えました。次のように、正規表現を使用し\B[A-Za-z]+て単語の最初の文字以外のすべての文字と一致させ、awk コマンドsubstr(tolower($i),2)を使用して同じ文字を小文字で提供しました。

echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1;i <= NF;i++) {sub("\B[A-Za-z]+",substr(tolower($i),2),$i)} print}' --> Abcd EFGH IJKL MNOP

最初の単語は正しく変換されていますが、残りの単語は変更されていません。残りの単語が適切に変換されなかった理由と、変換する方法を説明していただければ幸いです。

4

4 に答える 4

8

問題は、\B(ゼロ幅の非単語境界) は行頭でのみ一致するように見えるため$1機能しますが$2、次のフィールドは正規表現と一致しないため、置換されず大文字のままです。\B最初のフィールドを除いて一致しない理由がわからない... B は、任意の単語内のどこにでも一致する必要があります。

echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1; i<=NF; ++i) { print match($i, /\B/); }}'
2   # \B matches ABCD at 2nd character as expected
0   # no match for EFGH
0   # no match for IJKL
0   # no match for MNOP

とにかく結果を得るために (行の最初の文字のみを大文字にする) 、ループ$0を使用する代わりに (行全体)を操作できます。for

echo 'ABCD EFGH IJKL MNOP' | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2)) }'

または、各単語を個別に大文字にしたいが、次の場合awkのみ:

awk '{for (i=1; i<=NF; ++i) { $i=toupper(substr($i,1,1)) tolower(substr($i,2)); } print }'
于 2013-01-03T13:43:31.203 に答える
4

sub()関数または他の関数(など)を使用して正規表現を照合する場合gsub()は、次の形式で使用するのが最適です。

sub(/regex/, replacement, target)

これはあなたが持っているものとは異なります:

sub("regex", replacement, target)

したがって、コマンドは次のようになります。

awk '{ for (i=1;i<=NF;i++) sub(/\B\w+/, substr(tolower($i),2), $i) }1'

結果:

Abcd Efgh Ijkl Mnop

文字列関数に関するこの記事は一読する価値があるかもしれません。HTH。


私はあなたが望むことを達成するためのより簡単な方法があると言うべきです、例えば:を使用してGNU sed

sed -r 's/\B\w+/\L&/g'
于 2013-01-03T13:34:09.373 に答える
3

私の解決策は、正規表現subの最初の挿入での最初の部分を取得することです:substr

echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1 ; i <= NF ; i++) {sub(substr($i,2),tolower(substr($i,2)),$i)} print }'
Abcd Efgh Ijkl Mnop
于 2013-01-03T14:01:00.773 に答える
1

\Bの前に別の\文字を追加する必要があります

 echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1;i <= NF;i++)
 {sub("\\B[A-Za-z]+",substr(tolower($i),2),$i)} print}'

\ B awkだけで、この警告が表示されました。

awk:cmd。行:1:警告:エスケープシーケンス\B' treated as plainB '

于 2013-01-03T13:29:22.773 に答える