Hitung garis antara "X"


13

Saya ingin menghitung garis antara "X". Ini hanya sebuah contoh; Saya harus menerapkan kode ke hasil biologis yang kompleks. Saya akan berterima kasih jika Anda dapat menyarankan beberapa perintah, lebih disukai menggunakan awk, grepatau sedkarena saya akrab dengan mereka.

Contoh:

X
Y
Y
Y
X
Y
Y
Y
Y
X
Y
X

Output yang Diinginkan:

3
4
1

2
Anda mungkin tertarik pada Bioinformatika jika Anda akan bekerja di bidang ini.
terdon

Jawaban:


13

Dengan awk:

$ awk '!/X/{count++}/X/{print count; count = 0}' input

3
4
1

Tambahkan hitungan untuk setiap baris yang tidak mengandung X; cetak dan atur ulang hitungan untuk baris yang berisi X.


2
Jika baris pertama bukan merupakan X, jumlah baris pertama masih akan dihitung dan dikeluarkan dengan solusi ini, sampai baris pertama dengan Xdicocokkan. EX (Tidak dapat menambahkan baris baru dalam komentar, tetapi anggap ada garis baru antara masing-masing karakter; P): Y X Y Y X Y Y Yakan menampilkan:1 2
Dan

1
@muru ini tidak akan berfungsi jika tidak ada X di akhir (perlu ditambahkan END{if (count)print count}), dan menghasilkan baris kosong di mana X berada di awal untuk menghindari Anda dapat menambahkan /X/&&countdalam kondisi juga
αғsнιη

1
Heh. Satu komentar mengeluhkan bahwa pemimpin Ytidak boleh dihitung karena mereka tidak persis di antara dua X; yang lain mengeluh bahwa trailing Ys tidak dihitung karena mereka tidak persis di antara dua Xs. Saya akan menunggu OP untuk mengklarifikasi, jika perlu; Saya baik-baik saja dengan jawaban ini sampai saat itu.
muru

12
$ awk '/X/ && prev{print NR-prev-1} /X/{prev=NR}' file
3
4
1

Bagaimana itu bekerja:

Awk secara implisit membaca file input baris per baris.

  • /X/ && prev{print NR-prev-1}

    Untuk setiap baris yang berisi Xdan jika sebelumnya kita telah menetapkan nilai prev, kemudian cetak jumlah baris saat ini NR,, minus prevminus satu.

  • /X/{prev=NR}

    Untuk setiap baris yang berisi X, atur variabel prevke nomor baris saat ini NR,.


4
Hah, bagus. Penyalahgunaan NRmemberi saya ide:awk '/X/{print NR - 1; NR = 0}' foo
muru

Terima kasih, ini memberi saya info yang tepat. yang dibutuhkan.
Rhea

Muro: Bagus & rumit. Kecuali untuk mencetak satu nilai terlalu banyak, itu bekerja untuk saya di bawah gawk dan mawk. Saya ingin tahu apakah ini adalah perilaku yang dijamin. @ Edorton?
John1024

3
@ rhea Kecuali jika baris pertama Anda selalu merupakan X, ada perbedaan kecil dalam output antara 2 jawaban seperti yang saya jelaskan dalam komentar di bawah jawaban muru.
Dan

1
@ John1024 terima kasih! Saya harap ini akan membantu saya.
Rhea

6

awkPendekatan sederhana lain yang bekerja pada data sampel OP dan jika Xtidak di Xs pertama atau bahkan di Xs terakhir atau berulang.

awk -v RS='X' 'NF{print NF}' infile

Di atas adalah benar ketika hanya ada satu bidang di setiap baris dengan FS default spasi putih , jika tidak di bawah ini direvisi dalam kasus umum untuk menghitung secara teratur . Anda dapat memasukkan POLA Anda di tempat X di sana.

awk -F'\n' -v RS='X' 'NF>2{print NF-2}'

Input sampel:

X
Y YYY Y
YY
YY Y YY YY Y Y
X
Y Y Y
X
Y
Y
X
X

Outputnya adalah:

3
1
2

1

Sebagian besar jawaban di sini cocok dengan konten baris yang akan dihitung menggunakan ekspresi reguler yang disematkan ke dalam program Awk. Jika Anda perlu mencocokkan baris dengan konten yang mungkin mengandung karakter khusus (baik untuk Awk atau ekspresi reguler), akan lebih baik untuk benar-benar membandingkan string untuk kesetaraan. Karena itu saya mengusulkan skrip Awk berikut sebagai varian dari jawaban muru :

BEGIN {
    count = 0;
}

{
    if ($0 == needle) {
        if (count) {
            print count;
            count = 0;
        }
    } else {
        count++;
    }
}

Simpan sebagai file teks, mis. count-rows.awk, Dan aktifkan sebagai berikut:

awk -f count-rows.awk -v needle=X input

Anda dapat menyesuaikan nilai needlesesuai keinginan Anda. Keuntungan dari metode ini adalah Anda dapat menjalankan program dari skrip shell dengan nilai arbitrer needletanpa melarikan diri dari masalah:

awk -f count-rows.awk -v needle="$needle" input
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.