การนับบรรทัด (ไม่เว้นว่าง) ในการทุบตี


151

ใน Bash ฉันจะนับจำนวนบรรทัดโค้ดที่ไม่ว่างในโครงการได้อย่างไร


1
วิธีแก้ปัญหาด้านล่างมากมายใช้ได้กับไฟล์เดียว (เช่นfoo.c) มีความคิดเห็นเกี่ยวกับจำนวนบรรทัดในโปรเจ็กต์ (เช่นไฟล์จำนวนมากในโครงสร้างไดเร็กทอรีและไม่รวมไบนารีไฟล์)?
SolingPuzzles

5
@solvingPuzzles ฉันคิดว่าฉันสามารถตอบส่วนนั้นได้ สำหรับโซลูชันใด ๆ ที่ทำงานกับไฟล์เดียวเช่น "cat FILE | sed blah" คุณสามารถทำงานกับไฟล์จำนวนมากได้โดยแทนที่ "cat FILE" ด้วยคำสั่งที่แสดงชื่อไฟล์ที่จะทำงานเช่น "find. -name '* .py '"และไปป์ที่เป็น" xargs cat " เช่น "find. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
Jonathan Hartley

2
@JonathanHartley @solvingPuzzles ยังมีโปรแกรมเช่นนี้slocและclocที่นี่เพื่อทำการนับบรรทัดโค้ดเหล่านั้น
AsTeR

OP ที่นี่: เมื่อฉันถามปัญหานี้เป็นครั้งแรก 'cloc' ทำงานได้ไม่ดีกับรหัส Python ทุกวันนี้มันยอดเยี่ยมมาก
Jonathan Hartley

cloc ยังมีอยู่ในโมดูล npm และประหยัดเวลาได้มาก
กฤษณะเวดูลา

คำตอบ:


193
cat foo.c | sed '/^\s*$/d' | wc -l

และถ้าคุณพิจารณาบรรทัดว่างความคิดเห็น:

cat foo.pl | sed '/^\s*#/d;/^\s*$/d' | wc -l

ถึงแม้ว่านั่นขึ้นอยู่กับภาษา


24
ไม่แน่ใจว่าทำไมคุณถึงใช้แมวที่นั่น ใช้ foo.c หรือ foo.pl เป็นชื่อไฟล์เพื่อส่งผ่านไปยัง sed sed '/ ^ \ s * $ / d' foo.c | wc -l
Andy Lester

28
ติดนิสัย ฉันอ่านท่อจากซ้ายไปขวาซึ่งหมายความว่าฉันมักจะเริ่มต้นด้วย cat จากนั้นแอ็คชั่นแอ็คชั่นแอ็คชั่นและอื่น ๆ อย่างชัดเจนผลลัพธ์สุดท้ายก็เหมือนกัน
Michael Cramer

32
หากต้องการทำสิ่งนี้สำหรับไฟล์ทั้งหมดในโฟลเดอร์ย่อยทั้งหมดและเพื่อแยกความคิดเห็นด้วย '//' ให้ขยายคำสั่งนี้เป็น: find -type f -name '* .c' -exec cat {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc -l
Benjamin Intal

11
คุณสามารถอ่านจากซ้ายไปขวาโดยไม่ต้อง < foo.pl sed 'stuff' | wc -lUUOC:
jw013

22
โดยทั่วไปการพูด UUOC นั้นไม่สำคัญ แต่ความสามารถในการอ่านคือ
andersand

52
#!/bin/bash
find . -path './pma' -prune -o -path './blog' -prune -o -path './punbb' -prune -o -path './js/3rdparty' -prune -o -print | egrep '\.php|\.as|\.sql|\.css|\.js' | grep -v '\.svn' | xargs cat | sed '/^\s*$/d' | wc -l

ด้านบนจะให้จำนวนบรรทัดทั้งหมดของโค้ด (ลบบรรทัดว่าง) สำหรับโครงการ (โฟลเดอร์ปัจจุบันและโฟลเดอร์ย่อยทั้งหมดซ้ำ)

ในข้างต้น "./blog" "./punbb" "./js/3rdparty" และ "./pma" เป็นโฟลเดอร์ที่ฉันขึ้นบัญชีดำเพราะฉันไม่ได้เขียนรหัสลงไป นอกจากนี้. php, .as, .sql, .css, .js ยังเป็นนามสกุลของไฟล์ที่ถูกมองด้วย ไฟล์ใด ๆ ที่มีนามสกุลต่างกันจะถูกละเว้น


1
รูปแบบสำหรับแอพ Rails: ค้นหา -path './log' -prune -o -path './trunk' -prune -o -path './branches' -prune -o -path './vendor' -prune -o -path './tmp '-prune -o -print | egrep '\ .rb | \ .erb | \ .css | \ .js | \ .yml' | grep -v 'svn' | xargs cat | sed '/ ^ \ s * $ / d' | ห้องสุขา -l
ก่อให้เกิด

1
คุณจำเป็นต้องเพิ่ม$การ grep (ที่...\.js$|...) feature.js.swpมิฉะนั้นมันจะตรงกับ
Xeoncross

คุณลืมการยึดดังนั้นจึงมีไฟล์ผิด และรุ่นที่เรียบง่ายยิ่งขึ้นด้วยการยึด:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Mark Jeronimus

36

หากคุณต้องการใช้อย่างอื่นที่ไม่ใช่สคริปต์เชลล์ให้ลองใช้CLOC :

cloc นับบรรทัดว่าง, บรรทัดความคิดเห็นและบรรทัดทางกายภาพของซอร์สโค้ดในภาษาการเขียนโปรแกรมจำนวนมาก มันเขียนทั้งหมดใน Perl โดยไม่มีการอ้างอิงภายนอกการแจกจ่ายมาตรฐานของ Perl v5.6 และสูงกว่า (โค้ดจากโมดูลภายนอกบางตัวถูกฝังอยู่ภายใน cloc) และดังนั้นจึงพกพาได้


2
เมื่อฉันถามคำถามนี้เป็นครั้งแรก 'cloc' นับ Python docstrings เป็นบรรทัดของรหัสซึ่งเป็น IMHO ที่ไม่ดี ตอนนี้ 'cloc' เวอร์ชั่นสมัยใหม่นับว่า Python docstrings เป็นความคิดเห็นซึ่งฉันชอบมากขึ้น
Jonathan Hartley

นี่คือคำตอบที่ถูกต้อง! ฉันเพิ่งลอง cloc ออกมาและทำงานได้ดี
LeeMobile

31

มีหลายวิธีในการทำเช่นนี้โดยใช้ยูทิลิตี้เชลล์ทั่วไป

ทางออกของฉันคือ

grep -cve '^\s*$' <file>

ซึ่งจะค้นหาบรรทัดใน <file> บรรทัดที่ไม่ตรงกับ (-v) ที่ตรงกับรูปแบบ (-e) '^ \ s * $' ซึ่งเป็นจุดเริ่มต้นของบรรทัดแล้วตามด้วยอักขระช่องว่าง 0 หรือมากกว่าตามด้วย ในตอนท้ายของบรรทัด (เช่นไม่มีเนื้อหาอื่น ๆ จากนั้นช่องว่าง) และแสดงจำนวนของการจับคู่สาย (-c) แทนการจับคู่สายตัวเอง

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

$ grep -cve '^\s*$' *.hh

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39

2
ขอบคุณ! บังเอิญ wc ให้นับสำหรับแต่ละไฟล์ที่กำหนดรวมทั้งหมด
Jonathan Hartley

1
ไม่ว่าคุณจะทำการไพพ์เข้าไป แต่มันจะนับเป็นไฟล์เดียว
SpoonMeiser

นี่คือคำตอบที่ดีที่สุดในความคิดของฉัน
simhumileco

-eไม่จำเป็น. นั่นเป็นตำแหน่งปกติของรูปแบบและคุณไม่ได้ทำอะไรที่ขี้ขลาดกับมัน แต่ก็ไม่มีอะไรผิดปกติกับความชัดเจนถ้านั่นคือสไตล์ของคุณ
Jacktose

13

'wc' นับบรรทัดคำตัวอักษรเพื่อนับบรรทัดทั้งหมด (รวมถึงบรรทัดว่าง) ใช้:

wc *.py

ในการกรองบรรทัดว่างคุณสามารถใช้ grep:

grep -v '^\s*$' *.py | wc

'-v' บอก grep ให้ส่งออกทุกบรรทัดยกเว้นที่ตรงกับ '^' คือจุดเริ่มต้นของบรรทัด '\ s *' เป็นศูนย์หรือมากกว่าตัวอักษรช่องว่าง '$' เป็นจุดสิ้นสุดของบรรทัด * .py เป็นตัวอย่างของฉันสำหรับ ไฟล์ทั้งหมดที่คุณต้องการนับ (ไฟล์ไพ ธ อนทั้งหมดใน dir ปัจจุบัน) ไปป์ที่เอาต์พุต ไปเลย

ฉันกำลังตอบคำถาม (ของแท้) ของตัวเอง ไม่พบรายการ stackoverflow ที่ครอบคลุมสิ่งนี้


5
\ W ไม่ตรงกับช่องว่าง แต่ตรงกับอักขระที่ไม่ใช่คำ มันตรงกันข้ามกับ \ w ตัวอักษรคำ \ W จะจับคู่ทุกอย่างที่ไม่ได้เป็นตัวอักษรและตัวเลขหรือขีดเส้นใต้และดังนั้นจะไม่ทำสิ่งที่คุณอ้างว่าทำที่นี่ คุณหมายถึง \ s
SpoonMeiser

9

คำสั่งนี้นับจำนวนบรรทัดที่ไม่ว่าง
cat fileName | grep -v ^$ | wc -l
grep -v ^ $ ฟังก์ชั่นการแสดงออกปกติละเว้นบรรทัดว่าง


คำตอบนี้ตรงไปตรงมาที่สุด
samthebest

2
ไม่จำเป็นต้องมีcatในห่วงโซ่นี้:grep -v ^$ fileName | wl -l
Aethalides

7
นอกจากนี้ยังไม่จำเป็นwc -lเพราะ grep มี-c:grep -vc ^$ fileName
Jacktose


5
cat 'filename' | grep '[^ ]' | wc -l

ควรทำเคล็ดลับได้ดี


3
ทำไมต้องใช้ cat และไปป์ไฟล์เป็น grep เมื่อคุณสามารถส่งชื่อไฟล์เป็นอาร์กิวเมนต์ให้ grep ได้ตั้งแต่แรก?
SpoonMeiser

จริงมันเป็นเพียงนามแฝงเก่า ๆ ที่ฉันมี ... มันเป็นหลักเหมือนกับโซลูชันของคุณแทนที่จะใช้อินเวอร์ส
curtisk

4
awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"

1
ฉันจะลงคะแนนนี้เพราะฉันไม่เคยเห็นใครใช้ preincrement ในสคริปต์ awk แต่น่าเสียดายที่นี่นับเฉพาะบรรทัดว่างเท่านั้น :) awk '!/^[[:space:]]*$/{++x} END{print x}'คุณหมายถึง หรือถ้าคุณเกลียดเชิงลบจริงๆawk '{y++} /^[[:space:]]*$/{++x} END{print y-x}';)
dannysauer

4
grep -cvE '(^\s*[/*])|(^\s*$)' foo

-c = count
-v = exclude
-E = extended regex
'(comment lines) OR (empty lines)'
where
^    = beginning of the line
\s   = whitespace
*    = any number of previous characters or none
[/*] = either / or *
|    = OR
$    = end of the line

ฉันโพสต์นี้เพราะตัวเลือกอื่น ๆ ให้คำตอบที่ผิดสำหรับฉัน สิ่งนี้ใช้ได้กับซอร์ส java ของฉันโดยที่บรรทัดความคิดเห็นเริ่มต้นด้วย / หรือ * (ฉันใช้ * ในทุกบรรทัดในความคิดเห็นแบบหลายบรรทัด)


นี่เป็นวิธีแก้ปัญหาที่ใช้การได้ สิ่งเดียวที่จะสังเกตเห็น: มันไม่นับความคิดเห็นหลายสาย
Amol

2

นี่คือสคริปต์ Bash ที่นับจำนวนบรรทัดของรหัสในโครงการ มันสำรวจต้นไม้ต้นกำเนิดซ้ำและไม่รวมบรรทัดว่างเปล่าและความคิดเห็นบรรทัดเดียวที่ใช้ "//"

# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"

countLines(){
  # $total is the total lines of code counted
  total=0
  # -mindepth exclues the current directory (".")
  for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
    # First sed: only count lines of code that are not commented with //
    # Second sed: don't count blank lines
    # $numLines is the lines of code
    numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`

    # To exclude only blank lines and count comment lines, uncomment this:
    #numLines=`cat $file | sed '/^\s*$/d' | wc -l`

    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

echo Source code files:
countLines
echo Unit tests:
cd spec
countLines

นี่คือผลลัพธ์ที่ดูเหมือนสำหรับโครงการของฉัน :

Source code files:
   2 ./buildDocs.sh
   24 ./countLines.sh
   15 ./css/dashboard.css
   53 ./data/un_population/provenance/preprocess.js
   19 ./index.html
   5 ./server/server.js
   2 ./server/startServer.sh
   24 ./SpecRunner.html
   34 ./src/computeLayout.js
   60 ./src/configDiff.js
   18 ./src/dashboardMirror.js
   37 ./src/dashboardScaffold.js
   14 ./src/data.js
   68 ./src/dummyVis.js
   27 ./src/layout.js
   28 ./src/links.js
   5 ./src/main.js
   52 ./src/processActions.js
   86 ./src/timeline.js
   73 ./src/udc.js
   18 ./src/wire.js
   664 in total
Unit tests:
   230 ./ComputeLayoutSpec.js
   134 ./ConfigDiffSpec.js
   134 ./ProcessActionsSpec.js
   84 ./UDCSpec.js
   149 ./WireSpec.js
   731 in total

สนุก! - เคอร์แรน


1

มันจะขึ้นอยู่กับจำนวนไฟล์ที่คุณมีในโครงการ ในทางทฤษฎีคุณสามารถใช้

grep -c '.' <list of files>

ที่ที่คุณสามารถเติมรายการไฟล์โดยใช้ยูทิลิตี find

grep -c '.' `find -type f`

จะให้จำนวนบรรทัดต่อไฟล์


1
. ตรงกับช่องว่าง วิธีนี้ใช้ได้ผลก็ต่อเมื่อคุณพิจารณาบรรทัดที่มีช่องว่างเท่านั้นที่จะไม่ว่างซึ่งในทางเทคนิคแล้วถึงแม้ว่ามันอาจไม่ใช่สิ่งที่คุณต้องการ
SpoonMeiser

1

สคริปต์เพื่อนับบรรทัดที่ไม่ว่างทั้งหมดซ้ำด้วยนามสกุลไฟล์ที่แน่นอนในไดเรกทอรีปัจจุบัน:

#!/usr/bin/env bash
(
echo 0;
for ext in "$@"; do
    for i in $(find . -name "*$ext"); do
        sed '/^\s*$/d' $i | wc -l ## skip blank lines
        #cat $i | wc -l; ## count all lines
        echo +;
    done
done
echo p q;
) | dc;

ตัวอย่างการใช้งาน:

./countlines.sh .py .java .html

ขอบคุณไปที่ @Andy Lester (+1 ในความคิดเห็นของคุณ) สำหรับส่วน "ไม่ว่าง" ของสูตร
Keith Pinson

ขอขอบคุณ @Michael Cramer (+1 ในโพสต์ของคุณ) ที่โพสต์ในตอนแรก (ไม่ต้องเพิ่มมากขึ้น) โซลูชัน "ไม่ว่างเปล่า"
Keith Pinson

1

หากคุณต้องการผลรวมของบรรทัดที่ไม่ว่างทั้งหมดสำหรับไฟล์ทั้งหมดของนามสกุลไฟล์ที่กำหนดตลอดทั้งโครงการ:

while read line
do grep -cve '^\s*$' "$line"
done <  <(find $1 -name "*.$2" -print) | awk '{s+=$1} END {print s}'

ARG แรกคือไดเรกทอรีฐานของโครงการที่สองคือนามสกุลไฟล์ ตัวอย่างการใช้งาน:

./scriptname ~/Dropbox/project/src java

มันน้อยกว่าชุดโซลูชั่นก่อนหน้า


อันนี้ได้รับรางวัลสำหรับการโทรด้วยส้อม + exec จำนวนมากที่สุดโดยเรียกใช้ grep หนึ่งครั้งต่อบรรทัดในแต่ละไฟล์ ;)
dannysauer

0
grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

ให้นับรวมสำหรับไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันและไดเรกทอรีย่อย

HTH!


\ W เป็นตัวอักษรที่ไม่ใช่คำ; สิ่งนี้จะไม่ตรงกับ${-[*]} + $@ตัวอย่างเช่น ซึ่งเป็นรหัสที่ถูกต้องแน่นอนที่ไหนสักแห่งในโลก ;) คุณหมายถึง \ s สำหรับพื้นที่
dannysauer

0

สิ่งนี้ให้นับจำนวนบรรทัดโดยไม่นับบรรทัดว่าง:

grep -v ^$ filename wc -l | sed -e 's/ //g' 


-3

มีโปรแกรมสำหรับสิ่งนี้บน linux ชื่อ 'wc'

แค่

wc -l *.c 

และมันช่วยให้คุณมีบรรทัดทั้งหมดและบรรทัดสำหรับแต่ละไฟล์


3
เฮ้ 'wc' ด้วยตัวเองไม่ได้ค้นหาส่วนย่อยและจะไม่กรองบรรทัดว่างทั้งคู่ถามอย่างชัดเจนในคำถาม
Jonathan Hartley

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