web-dev-qa-db-ja.com

2つ以上のドットがある線を抽出する

2つ以上のドットがある行(ファイル内)を抽出(またはカウント)する必要があります。行はドットで開始してはならず(endでドットを付けても問題ありません)、連続して2つのドットがあってはなりません(つまり、ドットはすべて非ドット文字で区切られています)。

出力例:

a.b.
a.b.com
a.b.c.
a.b.c.com

だがしかし:

a.com
a..b
a.b.c..d

私はこのコマンドをしました:

grep -P '^[^.]+\.([^.]+\.)+[.]+' file.txt | wc -l

しかし、一致する行は見つかりませんでした。どうすればよいですか?

3
user9371654
  1. \.[.]は同等です。どちらもリテラルドットに一致し、他の文字には一致しません。スタイルの問題として、1つを選んで一貫して使用します。
  2. 問題は、正規表現(つまり、パターン)の([^.]+\.)+の後に[.]+が続いていることです。これは、実際には[^.]+\.の後に[.]が続いたものと同等であり、結果として、grepはtext.text..を含む行、つまり行に2つのドットを探します。チェックすると、コマンドがa.b..に一致することがわかります。
  3. OK、修正はかなり簡単だと思います:
    grep -P '^ [^。] + \。([^。] + \。)+ [^。]* $
    つまり、[.][^.]に変更し(おそらくそれが本来の意味ですか?)、次の+*に変更し、$を追加します。いくつかのtext.グループの後に、ドット以外の任意の数の(ゼロ以上の)文字を、行の終わりまで要求/許可します。
  4. さらにシンプルなアプローチ(理解しやすい)は、です。
    grep -P '^ [^。] +\.. * \。' file.txt | grep -v '\。\。'
    最初のgrepは、ドット以外の文字で始まり、2つ以上のドットを含む行を検索します。 2番目のgrepは、2つの連続するドットがある行を削除します。
  5. grep … | wc -lを実行するのではなく、grep -c …を実行してください。

awkの使用:

$ cat file
.com
.c.c.c.c
a.b.
a.b.com
a.b.c.
a.b.c.com
a.com
a..b
a.b.c..d
$ awk -F . 'NF > 2 && !/^\./ && !/\.\./' file
a.b.
a.b.com
a.b.c.
a.b.c.com

ここでのawkプログラムは、ドットをフィールド区切り記号として使用します。 2つ以上のドットを持つラインは、2つより多いフィールドを持つラインと同じです。これがNF > 2テストテスト。最初の正規表現は、ドットで始まる行を破棄し、2番目の正規表現は、連続して2つ以上のドットを含む行を破棄します。残りの行が印刷されます。

grepも同じです。

grep '\..*\.' file | grep -v -e '^\.' -e '\.\.'

最初の式は、少なくとも2つのドットを含む行を抽出し、他の2つの式は、ドットで始まる行または2つの連続するドットを含む行を削除します。

またはsedを使用して、

sed -n '/^\./d; /\.\./d; /\..*\./p' file
1
Kusalananda

これは、次のようにルックアラウンドで実行できます。

$ grep -Pc '^(?!\.)(?!.*\.\..*)(?=.*\..*\.)' file.txt

読み方:

  • 私はラインの最初に立っており、私の右を向いています^
  • 行がリテラルドットで始まっていない(?!\.)
  • さらに先を見ると、2つの連続したリテラルドットはありません(?!.*\.\..*)
  • しかし、2つのドットは表示されますが、前回の先読みでは連続するドットが除外されていたため、これらの2つのドットは少なくとも1つの非ドット文字で区切る必要があります(?=.*\..*\.)
  • Q.E.D.
0
Rakesh Sharma