đếm (không trống) dòng mã trong bash


151

Trong Bash, làm thế nào để tôi đếm số dòng mã không trống trong một dự án?


1
Rất nhiều giải pháp dưới đây chỉ hoạt động cho một tệp (ví dụ foo.c). Bạn có suy nghĩ gì về số lượng dòng trong một dự án (ví dụ: nhiều tệp trong cấu trúc thư mục và loại trừ các tệp nhị phân) không?
giải quyết các vòi phun

5
@solvePu phun Tôi nghĩ rằng tôi có thể trả lời phần đó. Đối với bất kỳ giải pháp nào hoạt động trên một tệp, ví dụ: "cat FILE | sed blah", bạn có thể làm việc trên nhiều tệp bằng cách thay thế "FILE mèo" bằng một lệnh liệt kê tên tệp để hoạt động, ví dụ: "find. -Name '* .py '"và chuyển nó thành" xargs cat ". ví dụ: "tìm. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
Jonathan Hartley

2
@JonathanHartley @solvePu phun cũng có những chương trình như thế slocclocở đây để thực hiện những dòng mã đó.
AsTeR

OP ở đây: Khi tôi lần đầu tiên hỏi vấn đề này, 'cloc' đã không làm rất tốt với mã Python. Ngày nay thật tuyệt.
Jonathan Hartley

cloc cũng có sẵn như là một mô-đun npm và tiết kiệm rất nhiều thời gian.
Krishna Vedula

Câu trả lời:


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

Và nếu bạn xem xét các dòng bình luận trống:

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

Mặc dù, đó là ngôn ngữ phụ thuộc.


24
Không chắc chắn tại sao bạn đang sử dụng con mèo ở đó. Sử dụng foo.c hoặc foo.pl làm tên tệp để truyền cho sed. sed '/ ^ \ s * $ / d' foo.c | wc -l
Andy Lester

28
Chỉ cần thói quen. Tôi đọc các đường ống từ trái sang phải, có nghĩa là tôi thường bắt đầu với mèo, sau đó hành động, hành động, hành động, v.v ... Rõ ràng, kết quả cuối cùng là như nhau.
Michael Cramer

32
Để làm điều này cho tất cả các tệp trong tất cả các thư mục con và để loại trừ nhận xét với '//', hãy mở rộng lệnh này vào đây: find. -type f -name '* .c' -exec mèo {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc -l
Benjamin Intal

11
Bạn có thể đọc từ trái sang phải mà không cần UUOC : < foo.pl sed 'stuff' | wc -l.
jw013

22
Nói chung, UUOC không quan trọng, nhưng khả năng đọc là.
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

Ở trên sẽ cung cấp cho bạn tổng số dòng mã (dòng trống đã bị xóa) cho một dự án (thư mục hiện tại và tất cả các thư mục con theo cách đệ quy).

Trong "./blog" "trên. Ngoài ra .php, .as, .sql, .css, .js là phần mở rộng của các tệp đang được xem xét. Bất kỳ tập tin với một phần mở rộng khác nhau được bỏ qua.


1
biến thể cho ứng dụng Rails: find. -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' | mèo xargs | sed '/ ^ \ s * $ / d' | wc -l
đặt ra

1
Bạn cần thêm a $vào grep ( ...\.js$|...) nếu không nó sẽ khớp feature.js.swp.
Xeoncross 13/03/2015

Bạn đã quên neo, vì vậy nó bao gồm các tập tin sai. Và một phiên bản thậm chí còn đơn giản hơn với neo:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Mark Jeronimus

36

Nếu bạn muốn sử dụng một cái gì đó ngoài tập lệnh shell, hãy thử CLOC :

cloc đếm các dòng trống, dòng nhận xét và dòng vật lý của mã nguồn trong nhiều ngôn ngữ lập trình. Nó được viết hoàn toàn bằng Perl mà không phụ thuộc ngoài phân phối chuẩn của Perl v5.6 trở lên (mã từ một số mô-đun bên ngoài được nhúng trong cloc) và do đó khá dễ mang theo.


2
Khi tôi lần đầu tiên hỏi câu hỏi này, 'cloc' đã tính các tài liệu Python là các dòng mã, là IMHO tối ưu. Các phiên bản hiện đại của 'cloc' hiện coi các tài liệu Python là nhận xét, điều mà tôi thích hơn nhiều.
Jonathan Hartley

Đây là câu trả lời chính xác! Tôi chỉ thử cloc ra và nó làm công việc tốt.
LeeMobile

31

Có nhiều cách để làm điều này, sử dụng các tiện ích shell phổ biến.

Giải pháp của tôi là:

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

Điều này tìm kiếm các dòng trong <file> các dòng không khớp (-v) khớp với mẫu (-e) '^ \ s * $', là phần đầu của một dòng, theo sau là 0 hoặc nhiều ký tự khoảng trắng, theo sau ở cuối dòng (nghĩa là không có nội dung nào khác khoảng trắng) và hiển thị số lượng dòng phù hợp (-c) thay vì chính các dòng phù hợp.

Một lợi thế của phương pháp này so với các phương thức liên quan đến đường ống wc, là bạn có thể chỉ định nhiều tệp và nhận được một số lượng riêng cho mỗi tệp:

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

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

2
Cảm ơn! Ngẫu nhiên, wc không cung cấp số đếm cho mỗi tệp đã cho, cộng với tổng số.
Jonathan Hartley

1
Không phải nếu bạn đang tham gia vào nó, như là tiêu chuẩn được tính chỉ là một tệp.
SpoonMeiser

Đây là câu trả lời tốt nhất theo ý kiến ​​của tôi.
simhumileco

-ekhông cần thiết. Đó là vị trí vị trí bình thường của mẫu và bạn không làm gì sôi nổi với nó. Nhưng không có gì sai khi nói rõ ràng, nếu đó là phong cách của bạn.
Jacktose

13

'wc' đếm các dòng, từ, ký tự, vì vậy để đếm tất cả các dòng (bao gồm cả các dòng trống) sử dụng:

wc *.py

Để lọc các dòng trống, bạn có thể sử dụng grep:

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

'-v' nói với grep để xuất tất cả các dòng ngoại trừ những dòng khớp với '^' là bắt đầu của một dòng '\ s *' bằng 0 hoặc nhiều ký tự khoảng trắng '$' là kết thúc của một dòng * .py là ví dụ của tôi cho tất cả các tệp bạn muốn đếm (tất cả các tệp python trong thư mục hiện tại) đầu ra cho wc. Tắt bạn đi.

Tôi đang trả lời câu hỏi (chính hãng) của riêng tôi. Không thể tìm thấy một mục stackoverflow bao gồm điều này.


5
\ W không phải là đối sánh cho khoảng trắng, nó khớp với các ký tự không phải từ. Nó trái ngược với \ w, các ký tự từ. \ W Sẽ khớp với bất cứ thứ gì không phải là chữ và số, và do đó sẽ không làm những gì bạn yêu cầu ở đây. Ý bạn là \ s
SpoonMeiser

9

Lệnh này đếm số dòng không trống.
cat fileName | grep -v ^$ | wc -l
Hàm grep -v ^ $ biểu thức chính quy bỏ qua các dòng trống.


Câu trả lời này là đơn giản nhất
samthebest

2
Không cần cattrong chuỗi này:grep -v ^$ fileName | wl -l
Aethalides

7
Cũng không cần wc -lvì grep có -c:grep -vc ^$ fileName
Jacktose


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

nên làm tốt


3
Tại sao sử dụng cat và dẫn tập tin vào grep, khi bạn có thể truyền tên tệp làm đối số cho grep ở vị trí đầu tiên?
SpoonMeiser

đúng, đó chỉ là một bí danh cũ mà tôi có xung quanh ... về cơ bản nó giống như giải pháp của bạn thay vì sử dụng nghịch đảo
curtisk

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

1
Tôi đã bỏ phiếu này chỉ vì tôi thực sự chưa bao giờ thấy ai sử dụng preincrement trong một kịch bản awk, nhưng thật không may, điều này chỉ tính các dòng trống. :) Bạn có nghĩa awk '!/^[[:space:]]*$/{++x} END{print x}'. Hoặc, nếu bạn thực sự ghét tiêu cực , 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

Tôi đăng bài này vì các lựa chọn khác đã đưa ra câu trả lời sai cho tôi. Điều này hoạt động với nguồn java của tôi, trong đó các dòng bình luận bắt đầu bằng / hoặc * (tôi sử dụng * trên mỗi dòng trong nhận xét nhiều dòng).


Đây là một giải pháp khả thi. Điều duy nhất cần chú ý: nó không tính các bình luận nhiều dòng
Amol

2

Đây là một đoạn mã Bash đếm các dòng mã trong một dự án. Nó đi qua một cây nguồn theo cách đệ quy và nó loại trừ các dòng trống và các chú thích dòng đơn sử dụng "//".

# $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

Đây là kết quả đầu ra của dự án của tôi :

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

Thưởng thức! - Curran


1

Nó sẽ phụ thuộc vào số lượng tệp bạn có trong dự án. Về lý thuyết bạn có thể sử dụng

grep -c '.' <list of files>

Nơi bạn có thể điền vào danh sách các tệp bằng cách sử dụng tiện ích tìm kiếm.

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

Sẽ cung cấp cho bạn một số lượng dòng trên mỗi tập tin.


1
. phù hợp với khoảng trắng. Giải pháp này chỉ hoạt động nếu bạn coi một dòng chỉ chứa khoảng trắng là không trống, về mặt kỹ thuật, mặc dù nó có thể không phải là thứ bạn đang theo đuổi.
SpoonMeiser

1

Tập lệnh để đếm đệ quy tất cả các dòng không trống với phần mở rộng tệp nhất định trong thư mục hiện tại:

#!/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;

Sử dụng mẫu:

./countlines.sh .py .java .html

Cảm ơn, hãy truy cập @Andy Lester (+1 trên bình luận của bạn) cho phần "không trống" trong công thức.
Keith Pinson

Cũng xin cảm ơn @Michael Cramer (+1 trên bài đăng của bạn) vì đã đăng bài đầu tiên (hơi dài dòng hơn) giải pháp "không trống".
Keith Pinson

1

Nếu bạn muốn tổng của tất cả các dòng không trống cho tất cả các tệp của phần mở rộng tệp đã cho trong toàn bộ dự án:

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

Arg đầu tiên là thư mục cơ sở của dự án, thứ hai là phần mở rộng tập tin. Sử dụng mẫu:

./scriptname ~/Dropbox/project/src java

Nó ít hơn một bộ sưu tập các giải pháp trước đây.


Điều này nhận được giải thưởng cho số lượng cuộc gọi fork + exec lớn nhất bằng cách khởi chạy grep một lần trên mỗi dòng trong mỗi tệp. ;)
dannysauer

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

đưa ra tổng số cho tất cả các tệp trong thư mục hiện tại và các thư mục con của nó.

HTH!


\ W là ký tự không từ; điều này sẽ không khớp với một dòng như ${-[*]} + $@, ví dụ. Đó chắc chắn là mã hợp lệ ở đâu đó trên thế giới. ;) Ý bạn là \ s cho không gian.
dannysauer

0

Điều này đưa ra số lượng dòng mà không tính các dòng trống:

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

0
rgrep . | wc -l

đưa ra số lượng các dòng không trống trong thư mục làm việc hiện tại.


-3

Đã có một chương trình cho điều này trên linux gọi là 'wc'.

Chỉ

wc -l *.c 

và nó cung cấp cho bạn tổng số dòng và dòng cho mỗi tệp.


3
Chào. 'wc' tự nó không tìm kiếm các thư mục con và nó không lọc ra các dòng trống, cả hai đều được hỏi rõ ràng trong câu hỏi.
Jonathan Hartley

wcđếm các dòng trống. OP muốn đếm các dòng không trống. Đúng là anh ấy sẽ muốn sử dụng wc, nhưng chỉ sau khi nó được chỉnh sửa luồng bằngsed
EhevuTov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.