підрахунок (непорожні) рядки коду в баші


151

Як в Bash я рахую кількість непорожніх рядків коду в проекті?


1
Дуже багато рішень нижче просто працюють для одного файлу (наприклад, foo.c). Будь-які думки щодо загальної кількості рядків у проекті (наприклад, багато файлів у структурі каталогів та виключення бінарних файлів)?
розв’язання Пузлів

5
@solvingPuzzles Я думаю, що можу відповісти на цю частину. Для будь-якого рішення, яке працює на одному файлі, наприклад, "cat FILE | sed blah", ви можете працювати над багатьма файлами, замінивши "cat FILE" командою, в якій перераховані імена файлів, над якими можна працювати, наприклад "find. -Name" * .py '"та передайте" xargs cat ". напр. "find. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
Джонатан Хартлі

2
@JonathanHartley @solvingPuzzles також є такі програми, як slocі clocтут, щоб зробити ці підрахунки рядків коду.
AsTeR

ОП тут: Коли я вперше запитав цю проблему, "cloc" не дуже добре працював над кодом Python. У наш час це чудово.
Джонатан Хартлі

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
Енді Лестер

28
Просто звичка. Я читаю трубопроводи зліва направо, це означає, що я зазвичай починаю з кота, потім дії, дії, дії тощо. Ясно, що кінцевий результат той самий.
Майкл Креймер

32
Щоб зробити це для всіх файлів у всіх підпапках та виключити коментарі за допомогою '//', розкладіть цю команду до цього: find. -тип f -name '* .c' -exec cat {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc -l
Benjamin Intal

11
Ви можете читати зліва направо без UUOC: < foo.pl sed 'stuff' | wc -l.
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 -ath './branches' -prune -o -ath './vendor' -prune -o -path './tmp '-прун -о -принт | egrep '\ .rb | \ .erb | \ .css | \ .js | \ .yml' | grep -v 'svn' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l
poseid

1
Вам потрібно додати $до grep ( ...\.js$|...), інакше він збігатиметься feature.js.swp.
Xeoncross

Ви забули кріплення, тому воно містить неправильні файли. І ще простіша версія з прив’язкою:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Марк Єронімус

36

Якщо ви хочете використовувати щось інше, ніж скрипт оболонки, спробуйте CLOC :

cloc рахує порожні рядки, рядки коментарів та фізичні рядки вихідного коду багатьма мовами програмування. Він написаний повністю на Perl, без залежностей поза стандартним розподілом Perl v5.6 і вище (код з деяких зовнішніх модулів вбудований в cloc) і тому є досить портативним.


2
Коли я вперше задав це запитання, "cloc" вважав доктрини Python як рядки коду, що було неоптимальним IMHO. Сучасні версії 'cloc' тепер доктрини Python вважають коментарями, що мені подобається набагато більше.
Джонатан Хартлі

Це правильна відповідь! Я просто спробував завершити роботу, і це добре працює.
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 забезпечує підрахунок для кожного файлу, плюс загальний.
Джонатан Хартлі

1
Не, якщо ви все-таки підключаєтесь до нього, як правило, вважається лише одним файлом.
SpoonMeiser

Це найкраща відповідь на мій погляд.
simhumileco

-eне потрібно. Це нормальне місце розташування шаблону, і ви нічого з цим не робите. Але нічого поганого в тому, щоб бути явним, якщо це ваш стиль.
Джектоз

13

'wc' рахує рядки, слова, символи, тому для підрахунку всіх рядків (включаючи порожні) використовується:

wc *.py

Щоб відфільтрувати порожні рядки, ви можете використовувати grep:

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

'-v' повідомляє grep виводити всі рядки, за винятком тих, що відповідають '^' - це початок рядка '\ s *' - нуль або більше символів пробілу '$' - це кінець рядка * .py - мій приклад для всі файли, які ви хочете порахувати (усі файли python у поточному режимі), виводять трубу на wc. Іди.

Я відповідаю на власне (справжнє) запитання. Не вдалося знайти запис stackoverflow, який охоплював це.


5
\ W - це не збіг для пробілів, він відповідає несловним символам. Це протилежність \ w, символам слова. \ W Відповідатиме будь-чому, що не буквено-цифрове або підкреслення, і тому не буде робити те, що ви тут стверджуєте. Ви маєте на увазі \ s
SpoonMeiser

9

Ця команда рахує кількість порожніх рядків.
cat fileName | grep -v ^$ | wc -l
Функція регулярного вираження grep -v ^ $ - ігнорування порожніх рядків.


Ця відповідь є найпростішою
саммбест

2
У catцьому ланцюжку немає необхідності :grep -v ^$ fileName | wl -l
Еталіди

7
Немає потреби в wc -lтому, що -cgrep -vc ^$ fileName
греп


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

повинен зробити трюк просто чудово


3
Навіщо використовувати cat і передавати файл в grep, коли ви можете передати ім'я файлу в якості аргументу для grep в першу чергу?
SpoonMeiser

правда, це лише старий псевдонім, який у мене є ... він робить по суті те саме, що і ваше рішення, замість того, щоб використовувати зворотний
curtisk

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

1
Я би проголосував за це лише тому, що я буквально ніколи не бачив, щоб хто-небудь використовував посилення в сценарії 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 за ваш коментар) за "непорожню" частину рецепту.
Кіт Пінсон

Дякуємо також @Michael Cramer (+1 у вашому дописі) за те, що він опублікував (дещо більш багатослівний) "непростий" розчин.
Кіт Пінсон

1

Якщо ви хочете суму всіх непорожніх рядків для всіх файлів даного розширення файлу протягом проекту:

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

Перший аргумент - базовий каталог проекту, другий - розширення файлу. Використання зразка:

./scriptname ~/Dropbox/project/src java

Це трохи більше, ніж сукупність попередніх рішень.


Цей отримує нагороду за найбільшу кількість викликів fork + 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' сам по собі не шукає підкаталоги та не відфільтровує порожні рядки, про що явно запитується у запитанні.
Джонатан Хартлі

wcрахує порожні рядки. ОП хоче рахувати непорожні рядки. Це правда, що він захоче користуватися wc, але лише після редагування потоку з використаннямsed
EhevuTov
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.