`Wc -l` ile tek bir satırı nasıl alabilirim?


12

Geçmişimdeki belirli dosyaların satır sayısını vermek için bir git takma adı ekledim:

[alias]
lines = !lc() { git ls-files -z ${1} | xargs -0 wc -l; }; lc

Bununla birlikte, wc -l~ 100 bin satırdan fazla satırım varsa, toplamları rapor eder, ardından devam eder. İşte bir örnek:

<100k satır (istenen çıktı)

$ git lines \*.xslt
  46 packages/NUnit-2.5.10.11092/doc/files/Summary.xslt
 232 packages/NUnit-2.5.10.11092/samples/csharp/_UpgradeReport_Files/UpgradeReport.xslt
 278 total

> 100k hat (boru hattı yapmak zorunda kaldı grep "total")

$ git lines \*.cs | grep "total"
 123569 total
 107700 total
 134796 total
 111411 total
  44600 total

wc -lBir dizi alt toplamdan değil, gerçek bir toplamı nasıl alabilirim ?


Stackoverflow.com/questions/2501402/… 'a göre sorun xargsdeğil wc. Hala nasıl düzeltileceğiyle ilgileniyorum ve cevaplarda iyi bir çözüm göremiyorum.
Ehryk

3
Sürümünüz seçeneği wcdestekliyor --files0-frommu? O zaman yapabilirsiniz{ git ls-files -z ${1} | wc -l --files0-from=- ; }
Mark Plotnick

@MarkPlotnick Bence bu bir cevap olmayı hak ediyor.
terdon

Hayır! wc: unrecognized option '--files0-from=-'
Ehryk

Yanıtlar:


12

Bunu deneyin ve açık olduğunuz için özür dileriz:

cat *.cs | wc -l

veya git ile:

git ls-files -z ${1} | xargs -0 cat | wc -l

wcÇıktının hem bireysel sayım hem de toplamla çıktı gibi görünmesini istiyorsanız awk, ayrı ayrı satırları eklemek için kullanabilirsiniz :

git ls-files -z ${1} | xargs -0 wc -l |
awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next}
     {total+=$1;print}
     END {print total,"total"}'

wcSizin için önemli olduğu takdirde, bu kadar güzel sıralanmayacaktır . Bunu yapmak için, tüm girdiyi okumanız ve kaydetmeniz, toplamı hesaplamanız ve ardından hatırlanan satırların biçimlendirilmiş bir çıktısını yazdırmak için bu alan genişliğini kullanmadan önce alan genişliğini hesaplamak için toplamı kullanmanız gerekir. Ev yenileme projeleri gibi, awksenaryolar hiçbir zaman gerçekten bitmez.

(Hevesli editörlere not: ilk koşuldaki düzenli ifade awk, adı "toplam" ve bir boşluk ile başlayan bir dosya olduğunda; aksi takdirde durum çok daha basit olabilirdi $2 == "total".)


Bu işe yarar, ancak yalnızca toplamı ( git ls-files -z ${1} | xargs -0 cat | wc -l) çıktılar . Ancak, yukarıdaki ilk örneğimde olduğu gibi wc -l tarafından sağlanan dosya başına satır sayısı eksik. Burada her iki dünyanın en iyisini elde etmenin herhangi bir yolu var mı?
Ehryk

Ya da, bu çok zorsa, bir anahtara parçalanırsa, bir anahtar ne olur: sadece toplamı verin, eğer olmazsa, toplam çıktı ile dosya başına normal wc'yi verin?
Ehryk

@Ehryk: Sadece iki kez yapabilirsin, bir kez grep -vtoplam çizgileri bırakmak için yaptığın yol ve bir kez de toplam toplamı almayı öneririm. Veya düzenlenen cevapta awk çözümünü deneyebilirsiniz,
rici

+1: "Ev yenileme projeleri gibi, awk komut dosyaları hiçbir zaman gerçekten bitmez."
Ehryk

Büyüleyici bir şekilde çalıştı. Nihai git ls-files -z ${1} | xargs -0 wc -l | awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next} {total+=$1;print} END {print "\n Total:",total,"lines"}'
sonucum

7

Linux çalıştırıyorsanız, wcmuhtemelen GNU Coreutils'ten gelir ve sayılacak --files0-fromNUL tarafından sonlandırılan dosya adlarının keyfi olarak uzun bir listesini içeren bir dosyayı (veya stdin) okuma seçeneğine sahiptir . GNU coreutils wc dokümantasyon dosya adları listesi çok uzun bir komut satırı uzunluğu sınırı aşabilir olmasıdır yararlı olur" diyor. Böyle durumlarda, parçalar halinde listeyi böler ve wc baskı yapar çünkü Xargs aracılığı wc istenmeyen çalışan tüm liste yerine her bir alt liste için toplam. "

Bu yüzden şunu deneyin:

lc() { git ls-files -z ${1} | wc -l --files0-from=- ; } 

Düzenleme: Senin wcson binyıl olduğundan ve bu seçeneği yok, burada awk"toplam" adlı herhangi bir dosya var ve yok varsayalım, daha taşınabilir bir çözümdür . wcHerhangi bir totalsatırın çıkışını filtreleyecek, bunun yerine bunları özetleyecek ve sonunda genel toplamı yazdıracaktır.

Bilmediğim bir şey, gittakma ad uygulamasının değiştirilmeden geçirilmesi gereken tek tırnak içinde $1ve $2içinde sorun olup olmayacağıdır awk.

lc() {
  git ls-files -z ${1} |
  xargs -0 wc -l |
  awk 'BEGIN { total=0; } { if (NF==2 && $2 == "total") total += $1; else print; } END { print total, "total"; }' ;
}

Linux çalıştırmıyorum, Windows için Git msngit.github.io (msysgit) git bash isteminde .
Ehryk

TAMAM. Yani xargsve wcsen koşu Cygwin gelmektedir? Çıktısını yapıştırabilir misiniz wc --version?
Mark Plotnick

Tam bir cygwin kurulumundan $ wc --version wc (GNU textutils) 2.0 Written by Paul Rubin and David MacKenzie. Copyright (C) 1999 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
değiller

Windows çalıştırılabilir bir dolu,C:\Program Files (x86)\Git\bin\wc.exe
Ehryk

@Ehryk Msysgit, Linux araçlarının bir limanıdır, ancak eski sürümlere sahip olma eğilimindedir, bu yüzden olmayabilir --files0-from.
Gilles 'SO- kötü olmayı bırak'

4

Sorun, xargskomutu birden çok çalışmaya böldüğü wciçin, her seferinde toplamı bildiriyor. Birkaç seçeneğiniz var, işleri oldukları gibi tutabilir ve wcçıktıyı ayrıştırabilirsiniz :

git ls-files -z ${1} | xargs -0 wc -l | awk '/total/{k+=$1}END{print k,"total"}';

Dosyaları kedi:

git ls-files -z ${1} | xargs -0 cat | wc -l

Veya xargstamamen atlayabilirsiniz ( buradan uyarlanabilir ):

unset files i; while IFS= read -r -d $'\0' name; do 
 files[i++]="$name"; 
done < <(git ls-files -z ${1} ) && wc -l "${files[@]}"

Dosya listeniz ARG_MAX'dan daha uzunsa bu bozulur .


-1
j=0; for i in *.php *.js *.css; do let j+=`wc -l $i | awk {'print $1'}`; done; echo $j;
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.