sed: グローバルに置換するときに先頭の空白を無視する

sed: グローバルに置換するときに先頭の空白を無視する

ファイル内の余分なスペースを置換する sed コマンドを書こうとしています。各単語の間にはスペースが 1 つだけ必要ですが、先頭のスペースとタブはそのままにしておきます。つまり、ファイルは次のようになります。

     This is     an indented      paragraph. The   indentation   should not be changed.
This is the     second   line  of the    paragraph. 

となります:

     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

私はさまざまなバリエーションを試してきました

/^[ \t]*/!s/[ \t]+/ /g

どのようなアイデアでも歓迎します。

答え1

$ sed 's/\>[[:blank:]]\{1,\}/ /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

使用した表現は1つまたは複数の[[:blank:]](スペースまたはタブ)に一致します言葉の後に、これらを 1 つのスペースに置き換えます。 は、\>単語文字と非単語文字の間のゼロ幅境界に一致します。

これは OpenBSD のネイティブ でテストされましたsedが、GNU でも同様に動作するはずですsed。GNU は単語境界の一致にsedも を使用します。\b

sed -Eこれを短縮するには次のようにも使えます

sed -E 's/\>[[:blank:]]+/ /g' file

繰り返しますが、\>が GNU で動作しない場合はsed\b代わりに を使用してください。


上記はサンプルテキストを正しく並べ替えていますが、とても句読点の後のスペースを削除する作業。例えば、

     This is     an indented      paragraph.        The   indentation   should not be changed.
This is the     second   line  of the    paragraph.

そのためには、もう少し複雑なバリエーションが役立ちます。

$ sed -E 's/([^[:blank:]])[[:blank:]]+/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

これにより、1 つ以上の空白文字が続く空白以外の文字が、空白以外の文字と 1 つのスペースに置き換えられます。

または、標準sed(そして、置換が行われるのは、2つ以上非スペース/タブの後のスペース/タブ)

$ sed 's/\([^[:blank:]]\)[[:blank:]]\{2,\}/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

答え2

POSIX 的には:

sed 's/\([^[:space:]]\)[[:space:]]\{1,\}/\1 /g; s/[[:space:]]*$//'

これは、非空白文字の後に続く 1 つ以上の空白文字のシーケンスを、その非空白文字と 1 つの SPC 文字に置き換え、末尾の空白文字を削除します。これにより、空白行と末尾の空白のある行 (Microsoft テキスト ファイルの行末にある CR を含む) が削除されます。

関連情報