Найти и сообщить номера строк пустых строк в текстовом файле

Да, вы можете плавно и легко перейти с одного LTS на следующий выпуск LTS:

Шаг Нажмите Alt + F2 и введите update-manager, а затем следуйте инструкциям на экране.

2
задан 7 August 2017 в 15:58

12 ответов

Использование awk

Метод для ввода нескольких файлов (см. конец сообщения) является наиболее надежным.

Вход одного файла:

awk 'BEGIN { printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Секция BEGIN выполняется до обработки входного файла.

ARGV[1] - это имя входного файла. Это соответствует переменной awk FILENAME, которая не работает в секции BEGIN.

!NF соответствует строкам, которые пусты или которые содержат только разделители полей. По умолчанию разделителями полей являются пробелы и символы табуляции, поэтому строки, содержащие только пробелы и вкладки, считаются пустыми. NF (без восклицательного знака) соответствует строкам, содержащим данные, а добавление ! инвертирует совпадение.

NR - текущий номер строки входного файла. множественный вход файла

Чтобы предотвратить появление запятой перед первым совпадающим номером строки, оставьте строку sep неопределенной до тех пор, пока не напечатаете первое совпадение.

Секция END запускается после обработки входного файла. В этом примере он завершает вывод чисто, печатая символ новой строки в стиле Unix.

Пример вывода:

Line numbers of empty lines in file.txt: 8,13,15,20,25,28

Немного небрежно использовать имя строки без первой настройки он, даже если изначально содержит , он будет пустым. Вы можете явно установить строку sep пустым в секции BEGIN:

awk 'BEGIN { sep="" ; printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Несколько входных файлов:

awk 'FNR==1 && NR>1 { printf "\n" } FNR==1 { sep="" ; printf "Line numbers of empty lines in " FILENAME ": " } !NF { printf sep FNR ; sep="," } END { printf "\n" }' file1.txt file2.txt file3.txt

FNR аналогично NR, за исключением того, что счетчик номера строки FNR сбрасывается до 1 в начале каждого файла.

Раздел FNR==1 && NR>1 { printf "\n" } заставляет вывод каждого файла печатать на отдельной строке. Он печатает символ новой строки, когда обрабатывается первая строка каждого дополнительного входного файла, но не для первой строки инвертирует файл .

Пример вывода:

Line numbers of empty lines in file1.txt: 8,13,15,20,25,28 Line numbers of empty lines in file2.txt: 1,2,4,6,7,9,10 Line numbers of empty lines in file3.txt: 3,8,9,11,13,15
7
ответ дан 18 July 2018 в 08:58

perl:

Печать (printf("%s\n", $.)) номера строки, если она пуста (if /^$/):

perl -ne 'printf("%s\n", $.) if /^$/' file.txt

perl

Итерирование по перечисленным (start == 1) строкам файла и печать номера строки при пустом:

with open('file.txt') as f: for idx, line in enumerate(f, 1): if line.rstrip('\n') == "": print(idx)
3
ответ дан 18 July 2018 в 08:58

Для одного запуска файла:

$ printf "line numbers %s are empty in your file.\n"\ "$(grep --line-number '^$' file-name | tr ':\n' ', ')"

Какие выходы:

line numbers 2, 5, 7, 9, 10, are empty in your file.
2
ответ дан 18 July 2018 в 08:58

Вы можете найти пустые строки и их номера строк с помощью

grep -E --line-number --with-filename '^$' file.txt

Пример:

w3@aardvark:~(0)$ grep -E --line-number --with-filename '^$' file.txt file.txt:1: file.txt:3: file.txt:4: w3@aardvark:~(0)$ cat -n file.txt 1 2 Not empty 3 4 5 Not empty w3@aardvark:~(0)$

Если ваши «пустые» строки содержат пробелы или TAB, использование:

grep -E --line-number --with-filename '^\s*$' file.txt
8
ответ дан 18 July 2018 в 08:58

Pure Bash, используя файл примера foo из ответа Zanna:

i=0 while read line; do ((++i)) if [[ $line == '' ]]; then echo $i fi done < foo

Вывод:

1 3 5 7

Или вы можете предпочесть эквивалент Bash для Ответ Zanna с использованием enumerate():

cat -n foo | while read -r i line; do if [[ $line == '' ]]; then echo $i fi done
6
ответ дан 18 July 2018 в 08:58

sed сообщит номер строки с помощью команды =, чтобы вы могли использовать это выражение для сообщения номеров строк пустых строк (строки с ничем между ^ (начало строки) и $ (конец of line)):

sed -n '/^$/=' file

Мы используем параметр -n для подавления печати потока (номера строк печатаются отдельно от самих линий, когда мы используем =, поэтому нет p ] здесь, поэтому единственным выходом являются номера строк совпадающих строк.

$ sed -n '/^$/=' foo 1 3 5 7

(если строки 1, 3, 5 и 7 пусты в foo)

Вот пример, показывающий, как вы можете получить нужное взаимодействие с пользователем. Вы можете использовать любое решение вместо выражения sed в этих структурах ...

$ cat foo 2 4 6 8

Итак:

$ read -p "Enter file name: "; echo -e "The following lines are empty in "$REPLY":\n$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')" Enter file name: foo The following lines are empty in foo: 1 3 5 7

(Используйте tr '\n' ',', чтобы вместо этого получить запятую пробелов)

Вы можете сохранить как скрипт (я назову свой empline):

#!/bin/bash read -p "Enter file name: " echo -e "The following lines are empty in "$REPLY":\n\ $(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"

Сделать исполняемый файл сценария:

chmod u+x empline

Затем вы можете запустить его так:

$ ./empline Enter file name: foo The following lines are empty in foo: 1 3 5 7

Вы можете пропустить строку read и заменить "$REPLY" на "$1", чтобы использовать имя файла в качестве позиционного параметра (поэтому запустите ./empline foo ). Чтобы упростить использование, вы можете сделать функцию и добавить к концу своего ~/.bashrc:

function empline() { echo -e "The following lines are empty in "$1":\n\ $(sed -n '/^$/=' "$1" | tr '\n' ' ')" }

Это принимает имя файла как аргумент:

$ empline foo The following lines are empty in foo: 1 3 5 7
8
ответ дан 18 July 2018 в 08:58

Использование awk

Метод для ввода нескольких файлов (см. конец сообщения) является наиболее надежным.

Вход одного файла:

awk 'BEGIN { printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Секция BEGIN выполняется до обработки входного файла.

ARGV[1] - это имя входного файла. Это соответствует переменной awk FILENAME, которая не работает в секции BEGIN.

!NF соответствует строкам, которые пусты или которые содержат только разделители полей. По умолчанию разделителями полей являются пробелы и символы табуляции, поэтому строки, содержащие только пробелы и вкладки, считаются пустыми. NF (без восклицательного знака) соответствует строкам, содержащим данные, а добавление ! инвертирует совпадение.

NR - текущий номер строки входного файла. множественный вход файла

Чтобы предотвратить появление запятой перед первым совпадающим номером строки, оставьте строку sep неопределенной до тех пор, пока не напечатаете первое совпадение.

Секция END запускается после обработки входного файла. В этом примере он завершает вывод чисто, печатая символ новой строки в стиле Unix.

Пример вывода:

Line numbers of empty lines in file.txt: 8,13,15,20,25,28

Немного небрежно использовать имя строки без первой настройки он, даже если изначально содержит , он будет пустым. Вы можете явно установить строку sep пустым в секции BEGIN:

awk 'BEGIN { sep="" ; printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Несколько входных файлов:

awk 'FNR==1 && NR>1 { printf "\n" } FNR==1 { sep="" ; printf "Line numbers of empty lines in " FILENAME ": " } !NF { printf sep FNR ; sep="," } END { printf "\n" }' file1.txt file2.txt file3.txt

FNR аналогично NR, за исключением того, что счетчик номера строки FNR сбрасывается до 1 в начале каждого файла.

Раздел FNR==1 && NR>1 { printf "\n" } заставляет вывод каждого файла печатать на отдельной строке. Он печатает символ новой строки, когда обрабатывается первая строка каждого дополнительного входного файла, но не для первой строки инвертирует файл .

Пример вывода:

Line numbers of empty lines in file1.txt: 8,13,15,20,25,28 Line numbers of empty lines in file2.txt: 1,2,4,6,7,9,10 Line numbers of empty lines in file3.txt: 3,8,9,11,13,15
7
ответ дан 24 July 2018 в 19:13
  • 1
    Я бы предпочел использовать FNR == 1 и FILENAME вместо BEGIN и ARGV[1] (и FNR вместо NR, тогда он должен работать с несколькими файлами). – muru 7 August 2017 в 04:26
  • 2
    @muru - Спасибо! Я добавил метод для ввода нескольких файлов на основе вашего предложения. – Gaultheria 7 August 2017 в 20:02

perl:

Печать (printf("%s\n", $.)) номера строки, если она пуста (if /^$/):

perl -ne 'printf("%s\n", $.) if /^$/' file.txt

perl

Итерирование по перечисленным (start == 1) строкам файла и печать номера строки при пустом:

with open('file.txt') as f: for idx, line in enumerate(f, 1): if line.rstrip('\n') == "": print(idx)
3
ответ дан 24 July 2018 в 19:13
  • 1
    Я не знаю, как запускать скрипты perl в ubuntu – Adnan Ali 7 August 2017 в 15:26
  • 2
    @AdnanAli perl приходит по умолчанию с Ubuntu. В вашем случае использования просто запустите способ, который я сделал, или, если вам интересно, используйте скрипт с #!/usr/bin/env perl, являющийся shebang. – heemayl 7 August 2017 в 15:32
  • 3
    он ничего не показывает. Я только что проверил. Perl-скрипт не работает – Adnan Ali 7 August 2017 в 15:48
  • 4
    @AdnanAli Измените свой вопрос и добавьте образец ввода. – heemayl 7 August 2017 в 15:49

Для одного запуска файла:

$ printf "line numbers %s are empty in your file.\n"\ "$(grep --line-number '^$' file-name | tr ':\n' ', ')"

Какие выходы:

line numbers 2, 5, 7, 9, 10, are empty in your file.
2
ответ дан 24 July 2018 в 19:13

Вы можете найти пустые строки и их номера строк с помощью

grep -E --line-number --with-filename '^$' file.txt

Пример:

w3@aardvark:~(0)$ grep -E --line-number --with-filename '^$' file.txt file.txt:1: file.txt:3: file.txt:4: w3@aardvark:~(0)$ cat -n file.txt 1 2 Not empty 3 4 5 Not empty w3@aardvark:~(0)$

Если ваши «пустые» строки содержат пробелы или TAB, использование:

grep -E --line-number --with-filename '^\s*$' file.txt
8
ответ дан 24 July 2018 в 19:13
  • 1
    Почему вы используете -E? хороший, хотя +1;) – Ravexina 7 August 2017 в 04:59
  • 2
    Также выполняет задание: grep -n '^$' file.txt. Если вам нужны только цифры, труба в cut -d: -f1. – wjandrea 7 August 2017 в 05:28
  • 3
    @Ravexina Раньше было несколько программ grep (grep, egrep, fgrep), но современное программирование объединило их в один (и это стандарт POSIX). -E сообщает grep - Interpret PATTERN as an extended regular expression, например, ведет себя как старый egrep. – waltinator 7 August 2017 в 06:34
  • 4
    @waltinator Я думаю, что Равексина задается вопросом, почему вам нужно -E для простого шаблона, такого как ^$. – muru 7 August 2017 в 06:53
  • 5
    Да, как муру утверждает, что вы не используете ERE, по крайней мере, в своей первой команде, это был мой реальный вопрос ... – Ravexina 7 August 2017 в 07:08

Pure Bash, используя файл примера foo из ответа Zanna:

i=0 while read line; do ((++i)) if [[ $line == '' ]]; then echo $i fi done < foo

Вывод:

1 3 5 7

Или вы можете предпочесть эквивалент Bash для Ответ Zanna с использованием enumerate():

cat -n foo | while read -r i line; do if [[ $line == '' ]]; then echo $i fi done
6
ответ дан 24 July 2018 в 19:13

sed сообщит номер строки с помощью команды =, чтобы вы могли использовать это выражение для сообщения номеров строк пустых строк (строки с ничем между ^ (начало строки) и $ (конец of line)):

sed -n '/^$/=' file

Мы используем параметр -n для подавления печати потока (номера строк печатаются отдельно от самих линий, когда мы используем =, поэтому нет p ] здесь, поэтому единственным выходом являются номера строк совпадающих строк.

$ sed -n '/^$/=' foo 1 3 5 7

(если строки 1, 3, 5 и 7 пусты в foo)

Вот пример, показывающий, как вы можете получить нужное взаимодействие с пользователем. Вы можете использовать любое решение вместо выражения sed в этих структурах ...

$ cat foo 2 4 6 8

Итак:

$ read -p "Enter file name: "; echo -e "The following lines are empty in "$REPLY":\n$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')" Enter file name: foo The following lines are empty in foo: 1 3 5 7

(Используйте tr '\n' ',', чтобы вместо этого получить запятую пробелов)

Вы можете сохранить как скрипт (я назову свой empline):

#!/bin/bash read -p "Enter file name: " echo -e "The following lines are empty in "$REPLY":\n\ $(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"

Сделать исполняемый файл сценария:

chmod u+x empline

Затем вы можете запустить его так:

$ ./empline Enter file name: foo The following lines are empty in foo: 1 3 5 7

Вы можете пропустить строку read и заменить "$REPLY" на "$1", чтобы использовать имя файла в качестве позиционного параметра (поэтому запустите ./empline foo ). Чтобы упростить использование, вы можете сделать функцию и добавить к концу своего ~/.bashrc:

function empline() { echo -e "The following lines are empty in "$1":\n\ $(sed -n '/^$/=' "$1" | tr '\n' ' ')" }

Это принимает имя файла как аргумент:

$ empline foo The following lines are empty in foo: 1 3 5 7
8
ответ дан 24 July 2018 в 19:13
  • 1
    sed -n '/ ^ $ / =' не работает – Adnan Ali 7 August 2017 в 15:54
  • 2
    Вы указали правильное имя файла? Есть ли какие-либо символы на пустых строках? @AdnanAli – Zanna 7 August 2017 в 16:30

Другие вопросы по тегам:

Похожие вопросы: