特定の単語が正確にN回繰り返される行を取得するにはどうすればよいですか?


8

この特定の入力の場合:

How to get This line that this word repeated 3 times in THIS line?
But not this line which is THIS word repeated 2 times.
And I will get This line with this here and This one
A test line with four this and This another THIS and last this

この出力が必要です:

How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one

行全体を取得するには、「this」という単語が3つだけ繰り返されます。(大文字と小文字を区別しない一致)


4
広すぎる投票者にとって:質問はどのようにしてより具体的になるのでしょうか?
Jacob Vlijm

@JacobVlijm「可能な回答が多すぎる」ということです。ピック$RANDOM_LANGUAGE-誰かがその中の解決策を思いつくことができます。
muru

@muru反対に、1つの言語に制限すると、プログラミング(言語)中心の質問になります。今、それは問題中心の質問です。多分多くの可能な解決策(言語)がありますが、それほど明白な解決策はありません。
Jacob Vlijm、2015年

回答:


13

perlthis大文字と小文字を区別せずに自身を置き換え、置換の数をカウントします。

$ perl -ne 's/(this)/$1/ig == 3 && print' <<EOF
How to get This line that this word repeated 3 times in THIS line?
But not this line which is THIS word repeated 2 times.
And I will get This line with this here and This one
A test line with four this and This another THIS and last this
EOF
How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one

代わりに一致数を使用する

perl -ne 'my $c = () = /this/ig; $c == 3 && print'

あなたがGNU awkを持っているなら、非常に簡単な方法:

gawk -F'this' -v IGNORECASE=1 'NF == 4'

フィールドの数は、セパレーターの数より1つ多くなります。


なぜ交換するのですか?交換せずに直接数えることはできませんか?
αғsнιη

我々は数えることができます確かに、コードは少し長いです:stackoverflow.com/questions/9538542/...
muru

gawkコマンドに賛成票を投じます。
スリランカ

9

ソースファイルがtmp.txtであると仮定すると、

grep -iv '.*this.*this.*this.*this' tmp.txt | grep -i '.*this.*this.*this.*'

左側のgrepは、tmp.txtで大文字と小文字を区別しない「this」が4回以上出現しないすべての行を出力します。

結果は右側のgrepにパイプ処理され、左側のgrepの結果に3回以上出現するすべての行が出力されます。

更新:@Muruのおかげで、ここにこのソリューションのより良いバージョンがあります、

grep -Eiv '(.*this){4,}' tmp.txt | grep -Ei '(.*this){3}'

4をn + 1に、3をnに置き換えます。


これはN> 4の場合は失敗します。そして、最初grepはで終わる必要があります*
ps95、2015年

1
つまり、N = 50でこれを書くことはできません。問題は厳密に3であるため、2以下のすべての出力を破棄する別のgrepが必要thisです。grep -iv '.*this.*this.*this.*this.*' tmp.txt | grep -i '.*this.*this.*this.* |grep -iv '.*this.*this.'
ps95 2015年

@ prakharsingh95 n> 4でも失敗せず、最初のgrepで*は必要ありません。
スリランカ

1
@KasiyA私の答えをどう思いますか?
2015年

5
少し簡略化します。grep -Eiv '(.*this){4,}' | grep -Ei '(.*this){3}'これは、N = 50の場合に実用的になる可能性があります。
muru

9

Pythonでは、これは仕事をします:

#!/usr/bin/env python3

s = """How to get This line that this word repeated 3 times in THIS line?
But not this line which is THIS word repeated 2 times.
And I will get This line with this here and This one
A test line with four this and This another THIS and last this"""

for line in s.splitlines():
    if line.lower().count("this") == 3:
        print(line)

出力:

How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one

または、ファイルを引数として、ファイルから読み込むには:

#!/usr/bin/env python3
import sys

file = sys.argv[1]

with open(file) as src:
    lines = [line.strip() for line in src.readlines()]

for line in lines:
    if line.lower().count("this") == 3:
        print(line)
  • スクリプトを空のファイルに貼り付け、名前を付けて保存find_3.pyし、次のコマンドで実行します。

    python3 /path/to/find_3.py <file_withlines>
    

もちろん、「this」という単語は他の単語(または他の文字列や行セクション)に置き換えることができ、1行あたりの出現回数はその行の他の値に設定できます。

    if line.lower().count("this") == 3:

編集する

ファイルが大きい場合(数十万/数百万行)、以下のコードはより高速になります。ファイルを一度に読み込むのではなく、1行ごとにファイルを読み取ります。

#!/usr/bin/env python3
import sys
file = sys.argv[1]

with open(file) as src:
    for line in src:
        if line.lower().count("this") == 3:
            print(line.strip())

私はpythonのエキスパートではありませんが、ファイルから読み取るにはどうすればよいですか?感謝
αғsнιη

1
@KasiyAは、ファイルを引数として使用するように編集されました。
Jacob Vlijm、2015年

気になるだけ:なぜ2番目のコードスニペットでジェネレータを使用しなかったのですか?
muru

6

awkこれで少し遊ぶことができます:

awk -F"this" 'BEGIN{IGNORECASE=1} NF==4' file

これは次を返します:

How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one

説明

  • フィールドセパレーターをthisそれ自体に定義することです。このように、行には、単語thisが現れる回数と同じ数のフィールド+1が含まれます。

  • 大文字と小文字を区別しないようにするには、を使用しますIGNORECASE = 1。参照:マッチングでの大文字と小文字の区別を参照してください。

  • 次に、NF==4これらすべての行をthis正確に3回取得するように言うだけです。{print $0}(つまり、現在の行を出力する)はawk式がに評価されるときのデフォルトの動作であるため、これ以上のコードは必要ありませんTrue


すでに投稿しましたが、良い説明です。
muru

@muruあ、見なかった!お詫びと+1を差し上げます。
fedorqui

5

行が次の名前のファイルに格納されていると仮定しますFILE

while read line; do 
    if [ $(grep -oi "this" <<< "$line" | wc -w)  = 3 ]; then 
        echo "$line"; 
    fi  
done  <FILE

1
代わりに、sed ...コマンドを削除して-oオプションを追加できますgrep -oi ...
αғsнιη

よりシンプル:$(grep -ic "this" <<<"$line")
muru

2
@muruいいえ、-cオプションでは、各行の「this」単語の数ではなく、「this」に一致する行の数がカウントされます。
αғsнιη

1
@KasiyAああ、そうです。私の悪い。
muru

@KasiyAは、ないだろう-l-w、この場合に相当しますか?
ps95 2015年

4

Vimにいる場合:

g/./if len(split(getline('.'), 'this\c', 1)) == 4 | print | endif

これは一致した行を出力するだけです。


Vimを使用するときに、単語がn回出現する行を検索するための良い例です。
Sri

0

Rubyワンライナーソリューション:

$ ruby -ne 'print $_ if $_.chomp.downcase.scan(/this/).count == 3' < input.txt                                    
How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one

非常に単純な方法で機能します。ファイルをルビーのstdinにリダイレクトし、ルビーはstdinから行を取得し、chompand downcaseでクリーンアップして、scan().countサブストリングの出現回数を示します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.