Як я можу виправити зламані лінії в неправильних місцях?


11

Мій текстовий файл виглядає приблизно так:

This is one
sentence that is broken.
However this is a good one.
And this
one is
somehow, broken into
many.

Я хочу видалити символ нового рядка для будь-якого рядка, за яким слідує рядок, починаючи з малої літери.

Отже, це має бути:

This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.

Як я можу це зробити?

Редагувати: Тут є кілька справді хороших відповідей, але я вирішив прийняти першу, яка працювала і була найдавнішою. Дякую всім!


1
LaTeX? Проблема полягає в тому, що ви насправді не вказуєте правила правильного порушення речення. Ви хочете поставити все в порядку, включаючи пунктуацію закінчення речення в одному рядку? Але що робити, якщо у вас довге речення, і воно біжить за край вашого вікна?
jamesqf

1
Цікаво, що ти насправді намагаєшся вирішити? Можливо, вам слід скористатися форматуванням розмітки?
Wildcard

@JeffSchaller Дякую за нагадування! Я якось пропустив. :)

Відповіді:


7

спробуйте

awk '$NF !~ /\.$/ { printf "%s ",$0 ; next ; } {print;}' file

де

  • $NF !~ /\.$/ рядок відповідності, коли останній елемент не закінчується крапкою,
  • { printf "%s ",$0 друкуйте цей рядок із проміжним місцем та без подачі рядків,
  • next ; } отримати наступний рядок,
  • {print;} і роздрукувати його.

Я впевнений, що буде sedваріант.

Примітка: це буде працювати з рядком, що закінчується крапкою, однак умова у реченнях, що починаються з великої літери, не зливається. Дивіться відповідь Стефана Шазеласа.


Якщо вам подобається розумний (багато хто ні)awk 'ORS=$NF~/\.$/?"\n":" "'
dave_thompson_085

10

З awk:

awk -v ORS= '{print (NR == 1 ? "" : /^[[:lower:]]/ ? " " : RS) $0}
             END {if (NR) print RS}'

Тобто не додавати роздільник записів до кожного рядка (ORS порожній). Але додайте роздільник записів перед поточним рядком, якщо не в першому рядку, а поточний рядок не починається з малої літери. В іншому випадку додайте замість символу пробіл, за винятком першого рядка.


Коли я запускаю це, кілька пар слів з’єднуються. Наприклад, And thisone issomehow, broken intomany.я не знаю, awkале чи слід з'єднувати рядки <space>на додаток до RS? Або це помилка користувача?
B Layer

@BLayer, добре помічений, дякую. Слід виправити зараз.
Стефан Шазелас

Без проблем. Хоча дивується, звідки взялося 11 звернень. Має бути приємно, щоб люди просто припускали, що ти завжди правий. ;)
B Layer

4

У перл:

#!/usr/bin/perl -w
use strict;
my $input = join("", <>);
$input =~ s/\n([a-z])/ $1/g;
print $input;

Технічно ви хотіли замінити "новий рядок з нижчим регістром" на "пробіл і-з малої літери", що полягає в тому, що ядро ​​вищевказаного сценарію Perl:

  1. Прочитайте у введенні до рядка input.
  2. Оновіть inputзмінну, яка буде результатом операції пошуку та заміни.
  3. Роздрукуйте нове значення.

1
хороший!! переведений на однолінійку, perl -0777 -pe 's/\n([a-z])/ $1/g'і подібне можна зробити з GNU sed як sed -zE 's/\n([a-z])/ \1/g'(якщо вхідні дані не мають нульових символів)
Sundeep,

3
@ Sundeep, або perl -Mopen=locale -0777 -pe 's/\n(?=[[:lower:]])/ /g'для того, щоб він не обмежувався літерами ASCII.
Стефан Шазелас

4

З sedвами можна використовувати N;P;Dцикл (щоб завжди було два рядки в просторі шаблону, і якщо перший символ після нового рядка є малим, тоді замініть новий рядок пробілом) і test - таким чином після кожного sвведення ви перезапустите цикл:

sed -e :t -e '$!N;/\n[[:lower:]]/s/\n/ /;tt' -e 'P;D' infile

1
Я думаю, що я бачу, що тут відбувається, але розширена відповідь допоможе тим із нас, хто не дуже часто використовує петлі sed та шаблони.
Джо

@Joe - що ви маєте на увазі під «не дуже часто використовуючи простір шаблону» ? Ось де майже всі операції відбуваються - простір утримування - це "місце для зберігання" - ви нічого не можете зробити з даними, поки вони є. У всякому разі, я докладно пояснив , як тут працює цикл , так що я не буду над ним знову. Різниця тут полягає в тому, щоб перевірити, замінено чи ні - якщо тест виявився успішним, тоді ми переходимо до вершини скрипту, інакше це означає, що нічого не замінено та виконано. Повідомте мене, якщо це все ще незрозуміло. N;P;DtP;D
don_crissti

3

Використання sedта fmt:

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt
This is one sentence that is broken.

However this is a good one.

And this one is somehow, broken into many.

Сценарій sed вставляє новий рядок перед кожним рядком, який починається з великої літери (за винятком самого першого рядка введення). sedПотім виводиться висновок fmtдля переформатування отриманих абзаців.

Крім того, використовуйте, parякщо він встановлений. Це ще один переформатор абзацу, але набагато більш здатний, ніж fmtіз значно більшою кількістю функцій та можливостей.

Зауважте, що між кожним абзацом буде порожній рядок. Абзаци повинні бути відокремлені один від одного хоча б одним порожнім рядком. Без порожніх рядків увесь зразок введення переформатується у вигляді одного абзацу з кількома реченнями, наприклад:

$ fmt input.txt
This is one sentence that is broken.  However this is a good one.
And this one is somehow, broken into many.

Якщо вам потрібно буде видалити порожні рядки після переформатування, просто переведіть їх sedще раз, але це видалить ВСІ порожні рядки, включаючи будь-які, що були в оригінальному введенні. напр

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt | sed -e '/^$/d'
This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.

3

Ще один спосіб зробити це:

perl -lpe '$\ = /\.$/ ? $/ : $"' data

де: $\=> ORS, $/=> IRS= \n, $"=space

perl -pe '$_ .= <>, eof or redo if s/[^.]\K\n/ /' data

sed -e '
   :a
      /\.$/!N
      s/\n/ /
   ta
' data

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