Порахуйте кількість порожніх рядків у кінці файлу


11

У мене в кінці файлу є порожні рядки. Чи можу я grepрахувати кількість пустих рядків у кінці файлу, при цьому ім'я файлу передається як змінне в сценарії?


порахувати кількість послідовних порожніх рядків ?
RomanPerekhrest

2
@RomanPerekhrest Я б сказав так, інакше вони не були б "в кінці файлу"?
Sparhawk

'grep -cv -P' \ S 'ім'я файлу' буде рахувати загальну кількість порожніх рядків у файлі. Число лише наприкінці оподатковує мій мозок!
MichaelJohn

ОП попросив grep@MichaelJohn виграти за чистоту в моїй книзі.
bu5hman

2
@ bu5hman Але (як він визнає) не відповідає на питання. Так само і не ваша.
Sparhawk

Відповіді:


11

Якщо порожні рядки знаходяться лише в кінці

grep  -c '^$' myFile

або:

grep -cx '' myFile

Побили до
редакції

grep -cv . myFileце ще один спосіб його написання (для гравців з кодом). Але я знайшов рішення, grepякщо в файлі де-небудь є порожні рядки.
Філіппос

2
@Philippos, grep -cv .також вважатиме рядки, що містять лише байти, які не утворюють дійсних символів.
Стефан Шазелас

11

Просто для розваги, моторошний sed:

#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l

Пояснення:

  • /./адресує рядки з будь-яким символом, тому /./!адреси непусті рядки; для них Hкоманда додає їх до місця утримування. Таким чином, якщо для кожного порожнього рядка ми додали один рядок у простір утримування, завжди є ще один рядок, ніж кількість порожніх рядків. Ми піклуємося про це пізніше.
  • //hпорожній шаблон відповідає останньому регулярному виразу, який був будь-яким символом, тому будь-який не порожній рядок адресовано та переміщено до місця утримування hкомандою для "скидання" зібраних рядків до 1. Коли наступний порожній рядок буде доданий, знову буде два, як очікувалося.
  • $!dзупиняє сценарій без виводу для кожного, але останнього рядка, тому подальші команди виконуються лише після останнього рядка. Тому будь-які порожні рядки, які ми зібрали у просторі утримування, знаходяться в кінці файлу. Добре.
  • //d: dКоманда знову виконується лише для не порожніх рядків. Тож якщо останній рядок не був порожнім, sedвийде без жодного виводу. Нульові лінії. Добре.
  • x біржі містять простір та простір шаблону, тому зібрані лінії перебувають у просторі шаблону, який зараз обробляється.
  • Але ми пам’ятаємо, що одного рядка занадто багато, тому ми зменшуємо його, видаляючи один новий рядок за допомогою s/\n//.
  • Вуаля! Кількість рядків відповідає кількості порожніх рядків на кінці (зауважте, що перший рядок не буде порожнім, але кого це цікавить), тому ми можемо їх порахувати wc -l.

8

Ще кілька GNU tac/ tail -rваріантів:

tac file | awk 'NF{exit};END{print NR?NR-1:0}'

Або:

tac file | sed -n '/[^[:blank:]]/q;p' | wc -l

Зауважте, що на виході:

printf 'x\n '

Тобто там, де після останнього повного рядка є додатковий простір (який дехто може розглянути як додатковий порожній рядок, але за визначенням POSIX тексту не є дійсним текстом), вони дадуть 0.

POSIXly:

awk 'NF{n=NR};END{print NR-n}' < file

але це означає прочитати файл у повному обсязі ( tail -r/ tacчитав би файл назад з кінця у файлах, що шукаються). Це дає 1на виході printf 'x\n '.


6

Оскільки ви насправді просите grepрішення, я додаю це, покладаючись лише на GNU grep(добре, також використовуючи синтаксис оболонки та echo...):

#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))

Що я тут роблю? $(grep -c ".*" "$1")підраховує всі рядки у файлі, після чого ми підраховуємо файл без проміжків порожніх рядків.

І як їх отримати? $(grep -B42 . "$1"зіткнув би всі непусті рядки та 42 рядки перед ними, тому він надрукував би все до останнього непустого рядка, доки перед непустим рядком не більше 42 послідовних порожніх рядків. Щоб уникнути цього обмеження, я приймаю $(grep -cv . "$1")за параметр для -Bпараметра, який є загальною кількістю порожніх рядків, тому завжди досить великих. Таким чином я викреслив порожні рядки, і можна використовувати |grep -c ".*"для підрахунку рядків.

Блискуче, чи не так? (-;


+1, тому що це жахливий код, але він технічно відповідає на запитання, і я не можу терпіти вас відзначити ;-)
roaima

Грепмайстер. Ми не гідні.
bu5hman

+1 за хибність. Іншим (можливо, швидшим?) Варіантом буде tac | grepспочатку не пусте значення -m -A 42, а потім мінус одне. Я не впевнений, що є більш ефективним, але ви могли б wc -l | cut -d' ' -f1замість того, щоб чіпляти порожні рядки?
Sparhawk

Так, звичайно, ви можете зробити багато речей з tac, wcі cut, але тут я намагався обмежитися grep. Ви можете назвати це химерністю, я називаю це спортом. (-;
Філіппос

5

Ще одне awkрішення. Ця зміна скидає лічильник kщоразу, коли з’являється порожній рядок. Потім кожен рядок збільшує лічильник. (Отже, після першого непорожнього рядка довжини,. k==0) В кінці виводимо кількість ліній, які ми підрахували.

Підготуйте файл даних

cat <<'X' >input.txt
aaa

bbb
ccc



X

Порахуйте проміжні порожні лінії у вибірці

awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3

У цьому визначенні порожній рядок може містити пробіли або інші порожні символи; він ще порожній. Якщо ви дійсно хочете рахувати порожні рядки, а не порожні рядки, змініть NFна $0 != "".


Чому $0 > ""? Це використання, strcoll()яке було б менш ефективним, ніж те, $0 != ""яке використовується memcmp()у багатьох реалізаціях (POSIX використовувався для того, щоб вимагати його використання strcoll()).
Стефан Шазелас

@ StéphaneChazelas Я не вважав, що це $0 > ""може бути інакше $0 != "". Я, як правило, розглядаю awkяк "повільний" оператор (такий, що якщо я знаю, що у мене є великий набір даних як введення даних, і обробка є критичною за часом, я побачу, що я можу зробити, щоб зменшити суму, awkяку потрібно обробити - я використовували grep | awkконструкції в таких ситуаціях). Однак, швидко ознайомившись із тим, що я припускаю, є визначення POSIX, я не можу побачити жодної посилання на те strcoll()чи інше memcmp(). Що я пропускаю?
roaima

strcoll()== рядки повинні порівнюватися, використовуючи послідовну послідовність зіставлення, характерну для місцевості . Порівняйте з попереднім виданням . Я виховував це. Дивіться також austingroupbugs.net/view.php?id=963
Stéphane Chazelas

@ StéphaneChazelas це реалізація, де a <= b && a >= bне обов'язково те саме, що a == b. Ой!
roaima

Це випадок GNU awkабо bash(для його [[ a < b ]]операторів) в en_US.UTF-8 локалей в системах GNU, наприклад , для проти , наприклад (для bash, жоден з <, >, =повертає істину для тих , хто). Можливо, це помилка у визначенні цих
локалів

2

порахувати кількість послідовних порожніх рядків у кінці файлу

Твердий awk+ tacрозчин:

Зразок input.txt:

$ cat input.txt
aaa

bbb
ccc



$  # command line 

Дія:

awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
  • !NF- забезпечує поточний рядок порожнім (немає полів)
  • NR==++c- забезпечення послідовного порядку порожніх рядків. ( NR- номер запису, ++c- рівномірно збільшений допоміжний лічильник)
  • cnt++- лічильник порожніх рядків

Вихід:

3

1

IIUC, наступний закликаний сценарій count-blank-at-the-end.shзробив би цю роботу:

#!/usr/bin/env sh

count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))

printf "%s\n" "$num_of_blank_lines"

Приклад використання:

$ ./count-blank-at-the-end.sh FILE
4

Я перевірив це і в GNU bash, Android mkshі в ksh.


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