Bir metin dosyasının her satırındaki karakter sayısı nasıl yazdırılır


83

Bir metin dosyasının her satırındaki karakter sayısını bir unix komutu kullanarak yazdırmak istiyorum. Powershell ile bunun basit olduğunu biliyorum

gc abc.txt | % {$_.length}

ama unix komutuna ihtiyacım var.

Yanıtlar:


156

Awk kullanın.

awk '{ print length }' abc.txt

2
Bu, her satıra wc -c uygulamaktan birkaç kat daha hızlıdır!
aerijman

@aerijman bu tür problemler için genellikle en fazla performans farkını yaratan, süreç yaratma sayısıdır.
MarcH

Dosyadaki bir satır emoji içeriyorsa, bu beklenen uzunluğu üretmeyecektir.
user5507535

@ user5507535, gerçekte hangi “uzunluk” beklediğinize bağlıdır. Unicode için birçok olası tanım vardır (mawk bayt kullanır, gawk kontrol etmedi).
Jan Hudec

17
while IFS= read -r line; do echo ${#line}; done < abc.txt

POSIX olduğundan her yerde çalışmalıdır.

Düzenleme: William tarafından önerildiği gibi -r eklendi.

Düzenleme: Unicode işlemeye dikkat edin. Bash ve zsh, doğru bir şekilde ayarlanmış yerel ayar ile kod noktalarının sayısını gösterir, ancak tire baytları gösterir - bu nedenle kabuğunuzun ne yaptığını kontrol etmeniz gerekir. Ve sonra Unicode'da zaten birçok olası uzunluk tanımı var, bu yüzden gerçekte ne istediğinize bağlı.

Düzenle: IFS=Baştaki ve sondaki boşlukları kaybetmemek için önek ile .


+1, ancak ... giriş '\' içeriyorsa bu başarısız olur. Oku -r
William Pursell

Dosyadaki bir satır emoji içeriyorsa, bu beklenen uzunluğu üretmeyecektir.
user5507535

@ user5507535, aslında, beklediğiniz “uzunluk” a bağlıdır. Unicode için birçok olası tanım vardır (ancak bu durumda, farklı kabuklar aslında farklı şeyler yapacaktır).
Jan Hudec

Daima set IFS=üzerinde readkeyfi veri okumak isteyen zaman komuta. Yani IFS= read -r. kelime bölme yapmak için readkullanır ve IFStüm bölünmüş kelimeler daha sonra mevcut tek bir değişkene ( line) tekrar yapıştırılsa bile, sahip oldukları tüm orijinal ayırıcı karakterlerle veya potansiyel olarak farklı yalnızca biriyle tekrar yapıştırılmalarının garantisi yoktur. olanlar. Örneğin, varsayılan IFS ile satır 7 boşluk kaybederek foo barhaline gelebilir foo bar. (Stack Overflow'un bu açıklamadaki örnek dizedeki bitişik boşlukları nasıl kaybettiği gibi).
mtraceur

@mtraceur, dokümantasyon açıkça "kalan sözcüklerin ve bunların araya giren sınırlayıcılarının soyadına atandığını", böylece orijinal ayırıcıyla birlikte tekrar yapıştırıldıklarını söylüyor. Ancak bu durum, dikkat almaz lider ve sondaki gerçekten kaybolur sınırlayıcı. Öyleyse haklısın, IFSayarlanmalısın, ama sorun olmadığında daha ince.
Jan Hudec

4

Yukarıda listelenen diğer cevapları denedim, ancak büyük dosyalarla uğraşırken iyi çözümlerden çok uzaktalar - özellikle tek bir satırın boyutu mevcut RAM'in ~ 1 / 4'ünden fazlasını kapladığında.

Hem bash hem de awk, bu problem için gerekli olmamasına rağmen tüm satırı karıştırır. Yeterli belleğiniz olsa bile, bir satır çok uzun olduğunda Bash hata verir.

Son derece basit, oldukça optimize edilmemiş bir python betiği uyguladım, büyük dosyalarla (satır başına ~ 4 GB) test edildiğinde höpürdetmiyor ve verilenlerden çok daha iyi bir çözüm.

Bu, üretim için zaman açısından kritik kodsa, bunun gerçekten bir darboğaz olduğunu test ettikten sonra, fikirleri C'de yeniden yazabilir veya okuma çağrısında daha iyi optimizasyonlar gerçekleştirebilirsiniz (bir seferde yalnızca tek bir bayt okumak yerine).

Kod, yeni satırın bir satır besleme karakteri olduğunu varsayar, bu Unix için iyi bir varsayımdır, ancak Mac OS / Windows'ta YMMV. Son satır karakter sayısının gözden kaçırılmamasını sağlamak için dosyanın bir satır besleme ile bittiğinden emin olun.

from sys import stdin, exit

counter = 0
while True:
    byte = stdin.buffer.read(1)
    counter += 1
    if not byte:
        exit()
    if byte == b'\x0a':
        print(counter-1)
        counter = 0

1
Soru bir "metin" dosyası içindi. Satır başına 4 GB'ın bir metin dosyasının herhangi bir makul tanımına uyduğunu düşünmüyorum.
MarcH

3

İşte kullanım örneği xargs:

$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file

Bu "echo%", kabuktan alıntı yapılması gereken güvenli olmayan karakterleri işlemez. Ek olarak, "xargs" dosyanızı, orijinal göndericinin istediği gibi yalnızca satır başlarına değil, boşluklara ve satırsonlarına göre bölecektir.
sığır

1

Bunu dene:

while read line    
do    
    echo -e |wc -m      
done <abc.txt    

Demek echo -e | wc -mistedin, değil mi? Komutların gereksiz kullanımı; kabuk bir değişkendeki karakterleri sayabilir. Artı echo -etamamen uyumsuzdur ve mermilerin yarısında çalışır, bazı kaçış sekansıyla başlarken bazılarında çalışır, diğerlerinde hiçbir şey olmaz.
Ocak Hudec
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.