Не может заменить несколько пустых строк одной - PullRequest
0 голосов
/ 23 сентября 2018

Почему следующее не заменяет несколько пустых строк одной?

$ cat some_random_text.txt  
foo   



bar   




test  

и это не работает:

$ cat some_random_text.txt | perl -pe "s/\n+/\n/g"
foo  



bar  





test  

Я пытаюсь заменить несколько новых строк (т. Е. Пустых строк) одной пустой новой строкой, но регулярное выражение, которое я использую дляэто не работает, как вы можете видеть в примере фрагмента.
Что я испортил?

Ожидаемый результат:

foo

bar

test

Ответы [ 3 ]

0 голосов
/ 23 сентября 2018

Причина, по которой это не работает, заключается в том, что -p указывает perl обрабатывать ввод построчно, и в одной строке не может быть более одного \n.

Лучшая идея:

perl -00 -lpe 1
  • -00: включить режим абзаца (входные записи завершаются любой последовательностью из 2+ новых строк).
  • -l: включить режим автохомпинга (разделители входных записейобрезается автоматически, поэтому, поскольку мы находимся в режиме абзаца, все завершающие символы новой строки удаляются, а выходные записи добавляются "\n\n".
  • -p: включить автоматический ввод / вывод (основной код выполняется длякаждая входная запись; все, что осталось в $_, печатается автоматически).
  • -e 1: использовать фиктивную основную программу, которая ничего не делает.

Все вместе это ничего не делает, кроменормализуйте разделители абзаца ровно до двух символов новой строки.

0 голосов
/ 23 сентября 2018

Дано:

$ echo "$txt"
foo   



bar   




test  

Вы можете использовать sed, чтобы уменьшить количество пустых строк до одной \n:

$ echo "$txt" | sed '/^$/N;/^\n$/D'
foo   

bar   

test  

Еще проще, вы можете использовать cat -s:

$ echo "$txt" | cat -s            # same output 

В perl вкладыш idiomatic 1 должен использовать -00 для режима абзаца:

$ echo "$txt" | perl -00pe0       # same output 

А в awk вы можете использоватьРежим абзаца, установив RS=, а затем установите ORS= на то, что вы хотите заменить для прогонов \n:

$ echo "$txt" | awk '1' RS= ORS="\n\n"    # same output 

Икегами правильно заявляет, что printf 'a\n\n' | ... будет производить двазамыкающие пробелы с этими решениями.Это может или не может быть проблемой.

0 голосов
/ 23 сентября 2018

Вы выполняете следующую программу:

LINE: while (<>) {
   s/\n+/\n/g;
}
continue {
   die "-p destination: $!\n" unless print $_;
}

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


Простое исправление состоит в том, чтобы заставить Perl рассматривать весь файл как одну строку.Кроме того, вы не хотите заменять каждый перевод строки, а только те, которые находятся в последовательности двух или более, и вы хотите заменить последовательность двумя переводами строки.

perl -0777pe's/\n\n\K\n+//g; s^\n+//; s/\n\K\n\z//' some_random_text.txt

Вторая и третья заменыубедитесь, что в начале и в конце файла нет пустых строк.


Хотя чтение всего файла в память легко, это не обязательно.Желаемый результат также может быть достигнут путем сохранения флага, который указывает, была ли предыдущая строка пустой или нет.

perl -ne'if (/\S/) { print "\n" if $f; print; $f=0 } else { $f=1 }' some_random_text.txt

Это решение также удаляет пустые строки из начала и конца файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...