Bagaimana cara menghitung jumlah karakter dalam satu baris, kecuali karakter tertentu?


9

Ini adalah file bagian

N W N N N N N N N N N
N C N N N N N N N N N
N A N N N N N N N N N
N N N N N N N N N N N
N G N N N N N N N N N
N C N N N C N N N N N
N C C N N N N N N N N

Di setiap baris saya ingin menghitung jumlah total semua karakter yang bukan "N"

output keinginan saya

1
1
1
0
1
2
2

Gunakan seduntuk mengganti barang-barang yang tidak Anda pedulikan dan awkuntuk menghitung panjang yang tersisased 's/N//g ; s/\s//g' file | awk '{ print length($0); }'
Rolf

Jawaban:


13

Solusi awk GNU :

awk -v FPAT='[^N[:space:]]' '{ print NF }' file
  • FPAT='[^N[:space:]]'- pola yang mendefinisikan nilai bidang (karakter apa pun kecuali Nkarakter dan spasi)

Output yang diharapkan:

1
1
1
0
1
2
2


7

dengan asumsi bahwa hitungan diperlukan untuk setiap baris selain karakter spasi dan N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • nilai balik tradalah berapa banyak karakter yang diganti
  • c untuk melengkapi set karakter yang diberikan
  • Perhatikan penggunaan -lopsi, menghapus karakter baris baru dari jalur input untuk menghindari kesalahan satu per satu dan juga menambahkan karakter baris baru untuk pernyataan cetak


Solusi yang lebih umum

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -apilihan untuk secara otomatis membagi jalur input pada spasi putih, disimpan dalam @Farray
  • grep {$_ ne "N"} @Fmengembalikan array semua elemen @Fyang tidak cocok dengan stringN
    • setara regex akan menjadi grep {!/^N$/} @F
  • Penggunaan scalarakan memberikan sejumlah elemen array

6

Solusi awk alternatif :

awk '{ print gsub(/[^N[:space:]]/,"") }' file
  • gsub(...)- gsub()Fungsi mengembalikan jumlah penggantian yang dibuat.

Hasil:

1
1
1
0
1
2
2

6

awkPendekatan lain (akan mengembalikan -1 untuk baris kosong).

awk -F'[^N ]' '$0=NF-1""' infile

Atau dalam kompleks, itu akan mengembalikan -1 pada baris kosong, 0 pada baris spasi putih (Tab / Spasi) saja.

awk -F'[^N \t]+' '$0=NF-1""' infile

akan mencetak -1untuk garis kosong ... tapi kemudian itu mungkin diinginkan untuk membedakan garis yang hanya terdiri dari N / spasi vs garis kosong ...
Sundeep

1
@ Tetap Ya, itu benar. juga melihat pembaruan saya di mana baris hanya berisi Tab atau Spasi untuk menunjukkan sebagai 0
αғsнιη

5
  1. trdan skrip shell POSIX :

    tr -d 'N ' < file | while read x ; do echo ${#x} ; done
    
  2. bash,, kshdan zsh:

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    

1
dapat digunakan awk '{print length()}'untuk menghindari perulangan shell yang lebih lambat .. tapi kemudian orang bisa melakukan semuanya dengan awk sendiri ...
Sundeep

@ Simpan, Itu benar, ( jika keduanya dimulai pada saat yang sama), awkperulangan itu lebih cepat daripada perulangan shell. Tapi shell selalu ada di memori, dan awkmungkin tidak - ketika awkbelum dimuat, atau ditukar, overhead memuatnya, ( waktu yang hilang ), bisa lebih besar daripada keuntungan berjalan awk- terutama pada kecil lingkaran. Dalam kasus seperti itu, ( yaitu kasus ini), awkbisa lebih lambat .
agc

baik, tentu saja saya tidak khawatir tentang waktu untuk hal-hal kecil ... lihat unix.stackexchange.com/questions/169716/…
Sundeep

1
@Sundeep, saya lakukan khawatir. Beberapa waktu yang lalu saya menggunakan distro Linux berbasis floppy , yang dapat menjalankan floppy, dalam beberapa MB ram. Tidak perlu menggunakan awkdalam skrip shell bisa membuat sistem merangkak merangkak seperti itu. Secara umum: hambatan latensi yang sama berlaku untuk sistem dalam firmware terbatas, atau sistem apa pun di bawah beban berat.
agc

1

Kombinasi singkat trdan awk:

$ tr -d ' N' <file.in | awk '{ print length }'
1
1
1
0
1
2
2

Ini menghapus semua spasi Ns dari file input dan awkhanya mencetak panjang setiap baris.


0

Cara mudah lainnya adalah melakukannya dengan python, yang sudah diinstal sebelumnya di sebagian besar lingkungan unix. Letakkan kode berikut dalam file .py:

with open('geno') as f:
    for line in f:
        count = 0
        for word in line.split():
            if word != 'N':
                count += 1
        print(count)

Dan kemudian lakukan:

python file.py

Dari terminal Anda. Apa yang dilakukan di atas adalah:

  • untuk setiap baris dalam file bernama "geno"
  • atur penghitung ke 0 dan tambahkan setiap kali kita menemukan nilai! = 'N'
  • ketika akhir dari garis saat ini tercapai, cetak penghitung dan pergi ke baris berikutnya
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.