Bagaimana saya bisa mendapatkan baris di mana kata tertentu diulang tepat N kali?


8

Untuk input yang diberikan ini:

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

Saya ingin hasil ini:

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

Mendapatkan seluruh baris hanya mengandung tiga kata "ini" yang diulang. (kecocokan huruf besar-kecil)


4
Bagi pemilih yang terlalu luas: bagaimana mungkin suatu pertanyaan bisa lebih spesifik?
Jacob Vlijm

@JacobVlijm Dalam bahwa ada "kemungkinan jawaban terlalu banyak". Pilih $RANDOM_LANGUAGE- seseorang akan dapat menemukan solusi di dalamnya.
muru

@uru saya akan mengatakan yang sebaliknya, membatasi ke satu bahasa akan membuatnya menjadi pemrograman (bahasa) pertanyaan terpusat. Sekarang ini adalah pertanyaan yang berpusat pada masalah . Mungkin ada banyak solusi yang mungkin (bahasa), tetapi tidak begitu banyak yang jelas.
Jacob Vlijm

Jawaban:


13

Dalam perl, ganti thisdengan dirinya sendiri case-insensitive dan hitung jumlah penggantian:

$ 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

Alih-alih menggunakan hitungan kecocokan :

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

Jika Anda memiliki GNU awk, cara yang sangat sederhana:

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

Jumlah bidang akan lebih dari jumlah pemisah.


Mengapa ganti? kita tidak bisa menghitungnya langsung tanpa ganti?
αғsнιη

Memang kita bisa menghitung, kodenya sedikit lebih panjang: stackoverflow.com/questions/9538542/…
muru

Suara positif untuk perintah gawk.
Sri

9

Dengan asumsi file sumber Anda adalah tmp.txt,

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

Grep kiri menampilkan semua baris yang tidak memiliki 4 atau lebih kejadian case-insensitive dari "this" di tmp.txt.

Hasilnya disalurkan ke grep kanan, yang menampilkan semua baris dengan 3 kejadian atau lebih di hasil grep kiri.

Pembaruan: Berkat @Muru, ini adalah versi yang lebih baik dari solusi ini

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

ganti 4 dengan n + 1 dan 3 dengan n.


Ini akan gagal untuk N> 4. Dan yang pertama grepharus diakhiri *.
ps95

1
Maksud saya Anda tidak dapat menulis ini untuk N = 50. Dan pertanyaannya adalah tepat tiga sehingga Anda perlu grep lain yang membuang semua output yang mengandung kurang dari atau sama dengan dua this. grep -iv '.*this.*this.*this.*this.*' tmp.txt | grep -i '.*this.*this.*this.* |grep -iv '.*this.*this.'
ps95

@ prakharsingh95 Tidak gagal untuk n> 4 dan * tidak diperlukan di grep pertama.
Sri

1
@ KasiyA, apa pendapat Anda tentang jawaban saya?
Sri

5
Sederhanakan sedikit: grep -Eiv '(.*this){4,}' | grep -Ei '(.*this){3}'- ini mungkin membuatnya praktis untuk N = 50.
muru

9

Dalam python, ini akan melakukan pekerjaan:

#!/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)

output:

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

Atau untuk membaca dari file, dengan file sebagai argumen:

#!/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)
  • Rekatkan skrip ke file kosong, simpan sebagai find_3.py, jalankan dengan perintah:

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

Tentu saja kata "ini" dapat diganti dengan kata lain (atau bagian string atau baris lainnya), dan jumlah kemunculan per baris dapat diatur ke nilai lain apa pun di baris:

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

Edit

Jika file berukuran besar (ratusan ribu / jutaan baris), kode di bawah ini akan lebih cepat; itu membaca file per baris alih-alih memuat file sekaligus:

#!/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())

Saya bukan ahli python, bagaimana saya bisa membaca dari file? terima kasih
αғsнιη

1
@KasiyA diedit untuk menggunakan file sebagai argumen.
Jacob Vlijm

Hanya ingin tahu: Mengapa Anda tidak menggunakan generator di cuplikan kode kedua?
muru

6

Anda dapat bermain sedikit dengan awkini:

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

Ini mengembalikan:

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

Penjelasan

  • Apa yang kita lakukan adalah mendefinisikan pemisah bidang thisitu sendiri. Dengan cara ini, baris tersebut akan memiliki banyak bidang +1 sebanyak kali kata tersebut thismuncul.

  • Untuk membuatnya tidak sensitif, kami menggunakan IGNORECASE = 1. Lihat referensi: Sensitivitas Huruf dalam Pencocokan .

  • Kemudian, itu hanya masalah mengatakan NF==4untuk mendapatkan semua kalimat itu thistepat tiga kali. Tidak diperlukan lagi kode, karena {print $0}(yaitu, cetak baris saat ini) adalah perilaku default awkketika ekspresi dinilai True.


Sudah diposting , tapi penjelasannya bagus.
muru

@uru oh, saya tidak melihatnya! Saya minta maaf dan memberi +1 untuk Anda.
fedorqui

5

Dengan asumsi garis disimpan dalam file bernama FILE:

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

1
Terima kasih, Anda dapat menghapus sed ...perintah dan menambahkan -oopsi untuk grep -oi ...gantinya.
αғsнιη

Simpler:$(grep -ic "this" <<<"$line")
muru

2
@muru Tidak, -copsi akan menghitung jumlah baris yang cocok dengan kata-kata "ini" bukan jumlah "ini" di setiap baris.
αғsнιη

1
@ Kakya Ah, ya. Salahku.
muru

@KasiyA, bukankah -ldan -wakan setara dalam kasus ini?
ps95

4

Jika Anda berada di Vim:

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

Ini hanya akan mencetak garis yang cocok.


Contoh yang bagus untuk mencari baris dengan n kemunculan kata, saat menggunakan Vim.
Sri

0

Solusi Ruby satu-liner:

$ 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

Bekerja dengan cara yang cukup sederhana: kami mengarahkan file ke stdin ruby, ruby ​​mendapat garis dari stdin, membersihkannya dengan chompdan downcase, dan scan().countmemberi kami jumlah kemunculan substring.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.