ฉันจะได้รับบรรทัดทั้งหมดด้วย `wc -l 'ได้อย่างไร


12

ฉันได้เพิ่มนามแฝง git เพื่อให้การนับจำนวนบรรทัดของไฟล์เฉพาะในประวัติของฉัน:

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

อย่างไรก็ตามwc -lมีการรายงานผลรวมหลายรายการเช่นถ้าฉันมีมากกว่า ~ 100k บรรทัดจะรายงานยอดรวมสำหรับพวกเขาจากนั้นก็จะดำเนินการต่อ นี่คือตัวอย่าง:

<100k บรรทัด (เอาต์พุตที่ต้องการ)

$ 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 บรรทัด (ต้องไปที่ท่อgrep "total")

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

ฉันจะได้รับผลรวมจริงwc -lได้อย่างไรไม่ใช่ชุดผลรวมย่อย?


ตามstackoverflow.com/questions/2501402/...ปัญหาอยู่ที่ไม่xargs wcฉันยังสนใจที่จะแก้ไขและฉันไม่เห็นคำตอบที่ดีในการแก้ปัญหา
Ehryk

3
รุ่นของคุณwcรองรับ--files0-fromตัวเลือกหรือไม่ จากนั้นคุณสามารถทำได้{ git ls-files -z ${1} | wc -l --files0-from=- ; }
Mark Plotnick

@ MarkPlotnick ฉันคิดว่าสมควรได้รับคำตอบ
terdon

Nope wc: unrecognized option '--files0-from=-'
Ehryk

คำตอบ:


12

ลองทำสิ่งนี้และขออภัยในความไม่ชัดเจน:

cat *.cs | wc -l

หรือด้วย git:

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

หากคุณต้องการให้ผลลัพธ์ดูเหมือนจริงกับwcเอาต์พุตด้วยจำนวนที่นับและยอดรวมคุณสามารถใช้awkเพื่อเพิ่มแต่ละบรรทัด:

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

ที่จะไม่ถูกเรียงอย่างดีเช่นเดียวกับwcในกรณีที่มีความสำคัญกับคุณ ในการทำเช่นนั้นคุณจะต้องอ่านอินพุตทั้งหมดและบันทึกคำนวณผลรวมทั้งหมดจากนั้นใช้ผลรวมเพื่อคำนวณความกว้างของฟิลด์ก่อนใช้ความกว้างของฟิลด์นั้นเพื่อพิมพ์เอาต์พุตที่จัดรูปแบบของบรรทัดที่จดจำ เช่นเดียวกับโครงการปรับปรุงบ้านawkสคริปต์ไม่เคยเสร็จจริงๆ

(หมายเหตุถึงบรรณาธิการที่กระตือรือร้น: นิพจน์ปกติในawkเงื่อนไขแรกคือในกรณีที่มีไฟล์ที่ชื่อขึ้นต้นด้วย "รวม" และเว้นวรรคมิฉะนั้นเงื่อนไขอาจง่ายกว่า$2 == "total"นี้มาก)


ใช้งานได้ แต่ให้ผลรวมเท่านั้น ( git ls-files -z ${1} | xargs -0 cat | wc -l) อย่างไรก็ตามฉันไม่มีการนับจำนวนบรรทัดต่อไฟล์ที่ wc -l แสดงในตัวอย่างแรกของฉันด้านบน มีวิธีใดบ้างที่จะได้สิ่งที่ดีที่สุดของโลกทั้งสองนี้
Ehryk

หรือถ้ามันยากเกินไปสวิตช์จะเป็นอย่างไรถ้ามันพัง: เพียงแค่ให้ผลรวมถ้ามันจะไม่ให้ wc ต่อไฟล์ปกติด้วยเอาต์พุตทั้งหมด?
Ehryk

@Ehryk: คุณทำได้สองครั้งเมื่อคุณทำแบบนั้นgrep -vเพื่อลดจำนวนบรรทัดทั้งหมดและเมื่อฉันแนะนำให้ทำยอดรวมทั้งหมด หรือคุณอาจจะลองแก้ปัญหา awk ในคำตอบที่แก้ไข
RICI

+1: "เช่นเดียวกับโครงการปรับปรุงบ้านสคริปต์ awk ไม่เคยเสร็จจริงๆ"
Ehryk

ที่ทำงานเหมือนจับใจ ผลลัพธ์สุดท้ายของฉัน:git ls-files -z ${1} | xargs -0 wc -l | awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next} {total+=$1;print} END {print "\n Total:",total,"lines"}'
Ehryk

7

หากคุณใช้งาน Linux คุณwcอาจมาจาก GNU Coreutils และมี--files0-fromตัวเลือกในการอ่านไฟล์ (หรือ stdin) ที่มีรายชื่อไฟล์ที่ยกเลิกด้วย NUL แบบยาวโดยพลการ เอกสาร GNU coreutils wcกล่าวว่า "นี่จะเป็นประโยชน์เมื่อรายชื่อไฟล์เป็นตราบว่ามันอาจจะเกินข้อ จำกัด คำสั่งความยาวสาย. ในกรณีดังกล่าววิ่ง wc ผ่าน xargs เป็นที่พึงปรารถนาเพราะมันแยกรายการออกเป็นชิ้น ๆ และทำให้การพิมพ์ wc ยอดรวมสำหรับแต่ละรายการย่อยแทนที่จะเป็นรายการทั้งหมด "

ลองทำสิ่งนี้:

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

แก้ไข: เนื่องจากคุณwcมาจากสหัสวรรษที่ผ่านมาและไม่มีตัวเลือกดังกล่าวนี่เป็นโซลูชันแบบพกพาที่มากขึ้นโดยสมมติว่าคุณมีawkและไม่มีไฟล์ชื่อ "รวม" มันจะกรองเอาท์พุทของwc, ละเว้นtotalบรรทัดใด ๆและแทนที่จะรวมพวกเขาและพิมพ์ผลรวมทั้งหมดในตอนท้าย

สิ่งหนึ่งที่ผมไม่ทราบว่าเป็นว่าgitการดำเนินการนามแฝงจะมีปัญหากับ$1และภายในราคาเดียวซึ่งจะต้องมีการส่งผ่านไปยังไม่เปลี่ยนแปลง$2awk

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 อยู่ในพรอมต์ git bash ของ Git สำหรับ Windows msysgit.github.io (msysgit)
Ehryk

ตกลง. ดังนั้นxargsและwcคุณกำลังทำงานอยู่จาก Cygwin? คุณสามารถวางเอาท์พุตของwc --version?
Mark Plotnick

พวกเขาไม่ได้มาจากการติดตั้งแบบเต็มรูปแบบ cygwin:$ 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.
Ehryk

มันเต็มไปด้วย windows ที่ปฏิบัติการได้C:\Program Files (x86)\Git\bin\wc.exe
Ehryk

@Ehryk msysgit เป็นพอร์ตของเครื่องมือลินุกซ์ --files0-fromแต่ก็มีแนวโน้มที่จะมีรุ่นเก่าจึงไม่อาจมี
Gilles 'หยุดความชั่วร้าย'

4

ปัญหาคือการxargsแยกคำสั่งออกเป็นหลาย ๆ ครั้งดังนั้นจึงwcรายงานผลรวมในแต่ละครั้ง คุณมีตัวเลือกไม่กี่ตัวคุณสามารถรักษาสิ่งต่าง ๆ ที่พวกเขาเป็นและแยกวิเคราะห์wcผลลัพธ์:

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

คุณสามารถ cat ไฟล์:

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

หรือคุณสามารถข้ามxargsไปเลย (ดัดแปลงจากที่นี่ ):

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

ที่จะแตกถ้ารายชื่อของไฟล์ที่มีความยาวมากกว่าARG_MAXแม้ว่า


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.