web-dev-qa-db-ja.com

sedコマンドについて:sed 's / \ s \ s * / / g'

私はこのコマンドに出くわしました:

ls -l <directory> | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c  

sedオプションの\s\s*の目的を理解しているかどうかは、100%わかりません。

\sが空白を指していることを知っています。 2番目の\s*の前にあるため、2番目の空白の一致は0回以上発生します。

これは、sedが入力ストリームからの1つ以上の連続するスペースを単一のスペースに置き換えることを意味しますか?はいの場合、\s+の代わりに\s\s*を使用しないのはなぜですか?

3
MikeB

\sは、GNU正規表現のショートカットで、スペースまたはタブ文字に一致するPOSIX式[[:blank:]]を記述する方法です(\sは、改行がsed他の編集コマンドによる)\s表記は、もともとはPerl正規表現に由来しますが、Perl正規表現では、POSIX式の[[:space:]]のように機能し、スペース生成文字の幅広い配列と一致します。

コマンド

sed 's/\s\s*/ /g'

1つ以上の連続するスペース/タブを単一のスペースに置き換え、現在の行で一致がなくなるまで置換を繰り返します。

したがって、はい、代わりにs/\s+/gを使用することもできますが、これは基本的な式ではなく拡張(GNU)正規表現であるため、コマンドに-Eを追加する必要があります。

sed -E 's/\s+/ /g'

現在、これは非標準オプション(-Eand GNU固有の正規表現(\s)を使用しています。標準に準拠した方法でコマンドを作成するには、次のいずれかを使用する必要があります

sed 's/[[:blank:]][[:blank:]]*/ /g'

または

sed 's/[[:blank:]]\{1,\}/ /g'

ここで、\{1,\}は、拡張正規表現修飾子+および{1,}( "1つ以上")と同じ意味です。

あなたも使うことができます

tr -s '[:blank:]' ' '

これは同じことをしたでしょう。つまり、すべてのスペースとタブをスペースに変換し、連続するスペースの(-s)ランを1つのスペースに絞り込みます。

または、そのパイプラインでsedtailの機能を実行させて、

ls -l dir | sed '1d; s/[[:blank:]]\{1,\}/ /g' | cut -d ' ' -f 3 | sort | uniq -c

または、単にawkを使用します。

ls -l dir | awk 'NR > 1 { count[$3]++ } END { for (user in count) print user, count[user] }'

awkを使用すると、スペースを圧迫する必要がありません)

8
Kusalananda