hitung (tidak kosong) baris kode dalam bash

151

Di Bash, bagaimana cara menghitung jumlah baris kode yang tidak kosong dalam suatu proyek?

Jonathan Hartley
sumber
1
Banyak solusi di bawah ini hanya berfungsi untuk satu file (misalnya foo.c). Adakah pemikiran tentang jumlah baris toal dalam suatu proyek (misalnya banyak file dalam struktur direktori, dan tidak termasuk file biner)?
troubleshootingPuzzles
5
@solvingPuzzles Saya rasa saya bisa menjawab bagian itu. Untuk solusi apa pun yang bekerja pada satu file, misalnya "cat FILE | sed blah", Anda dapat bekerja pada banyak file dengan mengganti "cat FILE" dengan perintah yang mencantumkan nama file untuk beroperasi, misalnya "find. -Name '* .py '", dan pipa itu menjadi" xargs cat ". mis. "find. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
Jonathan Hartley
2
@JonathanHartley @solvingPuzzles ada juga program seperti slocdan clocyang ada di sini untuk menghitung jumlah baris kode tersebut.
AsTeR
OP di sini: Ketika saya pertama kali menanyakan masalah ini, 'cloc' tidak melakukan pekerjaan yang sangat baik pada kode Python. Sekarang ini luar biasa.
Jonathan Hartley
cloc juga tersedia sebagai modul npm dan menghemat banyak waktu.
Krishna Vedula

Jawaban:

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

Dan jika Anda menganggap komentar sebagai baris kosong:

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

Meskipun, itu tergantung pada bahasa.

Michael Cramer
sumber
24
Tidak yakin mengapa Anda menggunakan kucing di sana. Gunakan foo.c atau foo.pl sebagai nama file untuk diteruskan ke sed. sed '/ ^ \ s * $ / d' foo.c | wc -l
Andy Lester
28
Hanya kebiasaan. Saya membaca pipa dari kiri ke kanan, yang berarti saya biasanya mulai dengan kucing, lalu beraksi, beraksi, beraksi, dll. Jelas, hasil akhirnya sama.
Michael Cramer
32
Untuk melakukan ini untuk semua file di semua subfolder dan untuk mengecualikan komentar dengan '//', perluas perintah ini ke ini: find. -type f -name '* .c' -exec cat {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc-l
Benjamin Intal
11
Anda dapat dibaca dari kiri ke kanan tanpa UUOC: < foo.pl sed 'stuff' | wc -l.
jw013
22
Secara umum, UUOC tidak penting, tetapi mudah dibaca.
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

Di atas akan memberi Anda jumlah total baris kode (baris kosong dihapus) untuk proyek (folder saat ini dan semua subfolder secara rekursif).

Dalam "./blog" "./punbb" "./js/3rdparty" dan "./pma" di atas adalah folder yang saya daftar hitam karena saya tidak menulis kode di dalamnya. Juga .php, .as, .sql, .css, .js adalah ekstensi dari file yang sedang dilihat. File dengan ekstensi berbeda diabaikan.

Gilles
sumber
1
variasi untuk aplikasi 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' | xargs cat | sed '/ ^ \ s * $ / d' | wc-l
poseid
1
Anda perlu menambahkan a $ke grep ( ...\.js$|...) jika tidak akan cocok feature.js.swp.
Xeoncross
Anda lupa jangkar, jadi itu termasuk file yang salah. Dan versi yang lebih sederhana dengan penahan:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Mark Jeronimus
36

Jika Anda ingin menggunakan sesuatu selain skrip shell, coba CLOC :

cloc menghitung baris kosong, baris komentar, dan garis fisik kode sumber dalam banyak bahasa pemrograman. Ini ditulis seluruhnya dalam Perl tanpa ketergantungan di luar distribusi standar Perl v5.6 dan lebih tinggi (kode dari beberapa modul eksternal tertanam di dalam cloc) dan sangat portabel.

xsl
sumber
2
Ketika saya pertama kali mengajukan pertanyaan ini, 'cloc' menghitung dokumen Python sebagai baris kode, yang merupakan IMHO suboptimal. Versi modern 'cloc' sekarang menghitung dokumen Python sebagai komentar, yang sangat saya sukai.
Jonathan Hartley
Ini jawaban yang benar! Saya baru saja mencoba mencari dan berhasil dengan baik.
LeeMobile
31

Ada banyak cara untuk melakukan ini, menggunakan utilitas shell umum.

Solusi saya adalah:

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

Ini mencari baris dalam <file> baris tidak cocok (-v) yang cocok dengan pola (-e) '^ \ s * $', yang merupakan awal dari sebuah baris, diikuti oleh 0 atau lebih karakter spasi, diikuti pada akhir baris (mis. tidak ada konten selain spasi putih), dan tampilkan hitungan baris yang cocok (-c) alih-alih baris yang cocok itu sendiri.

Keuntungan dari metode ini dibandingkan metode yang melibatkan pemipaan wc, adalah Anda dapat menentukan beberapa file dan mendapatkan hitungan terpisah untuk setiap file:

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

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39
SpoonMeiser
sumber
2
Terima kasih! Kebetulan, wc memang menyediakan hitungan untuk setiap file yang diberikan, ditambah total.
Jonathan Hartley
1
Tidak jika Anda mem-pipkannya, standar dalam jumlah hanya satu file.
SpoonMeiser
Ini jawaban terbaik menurut saya.
simhumileco
-etidak perlu. Itulah lokasi posisi normal dari pola dan Anda tidak melakukan apa pun yang funky dengannya. Tetapi tidak ada yang salah dengan menjadi eksplisit, jika itu gaya Anda.
Jacktose
13

'wc' menghitung baris, kata, karakter, jadi untuk menghitung semua baris (termasuk yang kosong) gunakan:

wc *.py

Untuk menyaring baris kosong, Anda dapat menggunakan grep:

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

'-v' memberitahu grep untuk menampilkan semua baris kecuali yang cocok dengan '^' adalah awal dari sebuah baris '\ s *' adalah nol atau lebih karakter spasi putih '$' adalah akhir dari baris * .py adalah contoh saya untuk semua file yang ingin Anda hitung (semua file python dalam direktori saat ini) menampilkan output pipa ke wc. Pergilah.

Saya menjawab pertanyaan saya sendiri (asli). Tidak dapat menemukan entri stackoverflow yang membahas hal ini.

Jonathan Hartley
sumber
5
\ W bukan kecocokan untuk spasi putih, itu cocok dengan karakter non-kata. Ini kebalikan dari \ w, karakter kata. \ W Akan cocok dengan apa pun yang bukan alfanumerik atau garis bawah, dan karena itu tidak akan melakukan apa yang Anda klaim di sini. Maksud Anda
SpoonMeiser
9

Perintah ini menghitung jumlah baris yang tidak kosong.
cat fileName | grep -v ^$ | wc -l
grep -v ^ $ fungsi ekspresi reguler mengabaikan baris kosong.

garis pantai
sumber
Jawaban ini adalah yang paling mudah
samthebest
2
Tidak perlu catdalam rantai ini:grep -v ^$ fileName | wl -l
Aethalides
7
Juga tidak perlu wc -lkarena grep memiliki -c:grep -vc ^$ fileName
Jacktose
6
cat file.txt | awk 'NF' | wc -l
Jaydillan
sumber
suka kesederhanaan yang satu ini 👏🏼
Gerard
5
cat 'filename' | grep '[^ ]' | wc -l

harus melakukan trik dengan baik

singkat
sumber
3
Mengapa menggunakan cat dan pipa file ke grep, ketika Anda bisa memberikan nama file sebagai argumen untuk grep?
SpoonMeiser
benar, ini hanya alias lama yang saya miliki ... itu pada dasarnya sama dengan solusi Anda alih-alih menggunakan invers
curtisk
4
awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"
Ben Hoffstein
sumber
1
Saya memilih ini hanya karena saya benar-benar tidak pernah melihat orang menggunakan preincrement dalam skrip awk, tapi sayangnya ini hanya menghitung baris kosong. :) Maksud Anda awk '!/^[[:space:]]*$/{++x} END{print x}'. Atau, jika Anda benar-benar membenci negatif awk '{y++} /^[[:space:]]*$/{++x} END{print y-x}'
,;
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

Saya memposting ini karena pilihan lain memberikan jawaban yang salah bagi saya. Ini bekerja dengan sumber java saya, di mana baris komentar mulai dengan / atau * (saya menggunakan * pada setiap baris dalam komentar multi-baris).

sami
sumber
Ini adalah solusi yang bisa diterapkan. Satu-satunya hal yang perlu diperhatikan: tidak menghitung komentar multi-baris
Amol
2

Berikut skrip Bash yang menghitung baris kode dalam suatu proyek. Itu melintasi pohon sumber secara rekursif, dan mengecualikan baris kosong dan komentar baris tunggal yang menggunakan "//".

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

Seperti apa hasilnya untuk proyek saya :

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

Nikmati! - Curran

curran
sumber
1

Agak akan tergantung pada jumlah file yang Anda miliki di proyek. Secara teori Anda bisa menggunakan

grep -c '.' <list of files>

Di mana Anda dapat mengisi daftar file dengan menggunakan utilitas temukan.

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

Akan memberi Anda jumlah baris per file.

Linor
sumber
1
. cocok dengan spasi putih. Solusi ini hanya berfungsi jika Anda menganggap garis yang hanya berisi spasi kosong sebagai non-kosong, yang secara teknis, meskipun mungkin bukan yang Anda cari.
SpoonMeiser
1

Script untuk menghitung secara rekursif semua baris non-kosong dengan ekstensi file tertentu di direktori saat ini:

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

Penggunaan sampel:

./countlines.sh .py .java .html
Keith Pinson
sumber
Terima kasih ke @Andy Lester (+1 di komentar Anda) untuk bagian "tidak kosong" dari resep.
Keith Pinson
Terima kasih juga kepada @Michael Cramer (memberi +1 pada posting Anda) untuk awalnya memposting solusi "tidak kosong" (sedikit lebih bertele-tele).
Keith Pinson
1

Jika Anda ingin jumlah semua baris yang tidak kosong untuk semua file dari ekstensi file yang diberikan di seluruh proyek:

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

Arg pertama adalah direktori basis proyek, kedua adalah ekstensi file. Penggunaan sampel:

./scriptname ~/Dropbox/project/src java

Ini sedikit lebih dari kumpulan solusi sebelumnya.

Andy
sumber
Yang ini mendapat penghargaan untuk jumlah terbesar dari panggilan fork + exec dengan meluncurkan grep sekali per baris di setiap file. ;)
dannysauer
0
grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

memberikan jumlah agregat untuk semua file di direktori saat ini dan subdirektori.

HTH!

Belanda
sumber
\ W adalah karakter non-kata; ini tidak akan cocok dengan garis seperti ${-[*]} + $@, misalnya. Yang pasti kode yang valid di suatu tempat di dunia. ;) Maksud Anda untuk ruang.
dannysauer
0

Ini memberikan hitungan jumlah garis tanpa menghitung baris kosong:

grep -v ^$ filename wc -l | sed -e 's/ //g' 
mahesh
sumber
0
rgrep . | wc -l

memberikan jumlah baris tidak kosong dalam direktori kerja saat ini.

jean-emmanuel
sumber
-3

Sudah ada program untuk ini di linux yang disebut 'wc'.

Hanya

wc -l *.c 

dan itu memberi Anda total baris dan baris untuk setiap file.

G1i1ch
sumber
3
Hei. 'wc' dengan sendirinya tidak mencari subdir, dan tidak menyaring baris kosong, keduanya secara eksplisit diminta dalam pertanyaan.
Jonathan Hartley
wcmenghitung garis kosong. OP ingin menghitung garis yang tidak kosong. Memang benar dia akan ingin menggunakan wc, tetapi hanya setelah itu telah diedit menggunakan menggunakansed
EhevuTov