sed で大文字の後のスペースを削除する

sed で大文字の後のスペースを削除する

私は他のファイルを自動的に生成する bash スクリプトを書いていますが、いくつかの文字列を特定の方法でフォーマットする必要があります。具体的には、最後に抱えている問題は、大文字が 1 つずつ含まれている文字列と、大文字で始まる単語をフォーマットすることです。たとえば、次のようになります。

O S D Settings必要になるOSD Settings

最初のスペースを削除する sed コマンドがありますが、このコマンドは「D」(つまりO S D Settings-> OS Settings) も削除します。このコマンドは次のとおりです。

O S D Settings | sed 's/ \([A-Z]\)* \(A-Za-z]*\)/\1/g'

文字を失うことなく、個々の大文字間のスペースを削除する方法を知っている人はいますか?

答え1

これにより、次のような名前が処理されますA B ChadwickA B C D'Souza

A B cdeやなどのテキストA B CDEは変更されません。

\x00行の進行に合わせてスペースを削除し、名前ごとに変更をマークするために 2 つの一時的な null 文字を使用します。

:Nそして:S分岐先ラベル (任意の名前でかまいません)
tb分岐命令です。
t前のコマンドで置換が成功すると分岐しますs/../../
b無条件に分岐します。

sed -r ":N                                                # loop per name
         /(\<[A-Z]\> )+[A-Z][a-z']/{                      # line needs action
             s/((\<[A-Z]\> )+)([A-Z][a-z'])/\x00\1\x00\3/ # add \x00 markers
            :S                                            # loop per space
             s/(\x00[A-Z]+) (\<[A-Z]\>)/\1\2/             # delete a space
             t S                                          # any more spaces? 
             b N                                          # any more names?
         }; s/\x00//g"                                    # remove \x00

答え2

では難しいですsedが、perl大丈夫ならこの方法でできます

echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'

sedこれは先読みアサーションをサポートしていないため困難です。

テスト:

echo O S D | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D. | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo One O DDE T. S Asdf Q R Tee | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D\  | perl -p -e 's/([A-Z]) (?=.([^\w]|$))/$1/g'

雑な解決策が必要な場合はsed

echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

これはサンプルでは機能しますが、他のケースでは失敗します。

テスト:

echo O S D | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D. | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo One O DDE T. S Asdf Q R Tee | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D\  | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

答え3

これはあなたにとって役立つかもしれません:

echo "O S D Settings and B T W and A B C D'Souza too F Y I" |
sed ':a;s/\(\<[[:upper:]]\>\) \(\<[[:upper:]]\>\([^'\'']\|$\)\)/\1\n\2/g;ta;s/\n//g'
OSD Settings and BTW and ABC D'Souza too FYI

説明:

削除したいスペースを元の文字列に存在しない文字で置き換え、文字列全体でその選択した文字を削除します。 は、\nsed によって行区切り文字として使用されるため通常は存在できないため、適切な候補です。

答え4

最終的に、パイプ付きの sed を使用して、理解しやすいステートメントを取得しました。

echo O S D Settings | sed 's/\([A-Z][^ ]\)/_\1/g' | sed 's/ //g' | sed 's/_/ /g'

これで、不要なスペースがアンダースコアに置き換えられ、削除されるだけです。すべての回答に感謝します。

関連情報