Ubuntu 20.04でBashを使用しています。
私はファイルを持っています:
Hello hi 123
if a equals b
you
one abc two three four
dany uri four 123
sed
たった4ワードの行を見つける必要があります。これは私が書いたコードですが、うまくいかずにファイルを正確に印刷します。
sed "/[a-Z0-9+]{4}/g" F1
答え1
この問題は、次のようにフィールドを簡単に計算できるツールで解決する必要がありますawk
。
$ awk 'NF == 4' file
if a equals b
dany uri four 123
これは、現在のレコードのフィールド数を保持するNF
特殊変数を使用します。awk
デフォルトでは、レコードは1行で、フィールドは、行の先頭または末尾にある空のフィールドを除いて、1つ以上の空白文字(タブまたはスペース)で区切られた部分文字列です。上記のショートプログラムは、awk
正確に4つのフィールドを含むすべての行を出力します。
を使用する場合は、sed
スペースで区切られた部分文字列を一致させる必要があります。
sed
デフォルトの正規表現はデフォルトで使用され、表示される式は拡張正規表現修飾子を使用します{4}
。基本正規表現に対応する内容が作成されます\{4\}
。また、無効な文字範囲を使用しており、a-Z
使用したい文字クラスをで書くことをお勧めします[[:alnum:]]
。つまり、すべての英数字と一致するものです(includeが+
スペルが間違っていると仮定)。 「予約済みスペース」からデータをインポートするための末尾のg
コマンドが間違っているようです。
ここで私の一般的なアイデアは、各単語(空白ではなく1つ以上の文字)を単一の単語にx
圧縮してから、すべての空白文字(タブまたはスペース)を削除することです。結果の文字列がある場合はxxxx
元の行を印刷します(そうでない場合は行を削除し、すぐに次のループを開始します)。
sed -e h \
-e 's/[^[:blank:]]\{1,\}/x/g' \
-e 's/[^x]//g' \
-e '/^xxxx$/!d' \
-e g file
ここで、元の行は最初を使用して「予約済みスペース」に保存し、印刷する必要があるh
場合は再度取り出し、g
最後に使用します。 2番目から最後の行までd
のコマンドが実行されると、g
最後の行は考慮されません。
または拡張正規表現を使用してください。
sed -E -e h \
-e 's/[^[:blank:]]+/x/g' \
-e 's/[^x]//g' \
-e '/^xxxx$/!d' \
-e g file
テスト:
$ sed -e h \
> -e 's/[^[:blank:]]\{1,\}/x/g' \
> -e 's/[^x]//g' \
> -e '/^xxxx$/!d' \
> -e g file
if a equals b
dany uri four 123
[[:alnum:]]
(空白ではなく)代わりにクラスで単語文字を定義するには、[^[:blank:]]
上記の式を[^[:blank:]]
に変更します。[[:alnum:]]
違いは、GNU/Linux
orなどの文字列がUnix-system
各単語ではなく2つの単語として扱われることです。
答え2
GNUの使用sed
:
$ sed -E '/^\s*(\w+\s+){3}\w+\s*$/!d' infile
if a equals b
dany uri four 123
POSIXly 次のように書くことができます。
sed '/^[[:space:]]*\([_[:alnum:]][_[:alnum:]]*[[:space:]][[:space:]]*\)\{3\}[_[:alnum:]][_[:alnum:]]*[[:space:]]*$/!d' infile
答え3
私たちが作成した正規表現を活用しGNU sed
て、オプションの先行スペースを見つけ、正確に4対の非スペース+スペース、パターンスペースの終わりを見つけます。
$ sed -nE 'G;/^\s*(\S+\s+){4}$/P' F1
または、
sed -nE '
s/\S+/&/4;T # 3 or less chunks
s//&/5;t # 5 or more chunks
p # exactly 4 chunks
' F1
sed -E '
s/\S+/&/5; td # 5 or more chunks
s//&/4; t # exactly 4 chunks
:d;d # 3 or less or 5 or more
' F1
答え4
明らかにawk
このユースケースのためのより良いツールですが、これはOPが指定したものですsed
。
GNUを使用すると、sed
さまざまなソリューションが可能です。予約済みスペースの使用は次のとおりです。
$ cat -A file
Hello hi 123$
if a equals b$
you$
one abc two three four$
dany uri four 123$
one two three four$
five six ^Iseven eight $
$ sed -e 'h; s/^\s*//; s/\s*$//' -nre '/^\w+(\W+\w+){3}$/{g;p}' file
if a equals b
dany uri four 123
one two three four
five six seven eight
$
コマンドはsed
次のように単純化できます。
$ sed -nr '/^\s*(\w+)(\W+\w+){3}\s*$/p' file
代わりに、POSIX文字クラスを使用する以前のコマンドsed
の移植性が高い別のバージョンは次のとおりです。-E
-r
$ sed -En '/^[[:blank:]]*[[:alnum:]]+([[:blank:]]+[[:alnum:]]+){3}[[:blank:]]*$/p' file