Обработка Текста – Как Преобразовать Многострочный В Однострочный, Но Сохранить Абзацы

  • Автор темы Tan9
  • Обновлено
  • 22, Oct 2024
  • #1

Скажем, у меня есть куча текста (уценки), где каждое предложение находится на отдельной строке (для упрощения контроля версий в случае опечаток). Пример

 
 cat file.txt | ??? 
:

\S

Как я могу преобразовать каждый абзац в одну строку, чтобы он выглядел так:

.

Моя идея - найти и заменить новую строку \n character between a fullstop Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dictum sit amet justo donec enim diam vulputate. Nunc faucibus a pellentesque sit amet. Quis enim lobortis scelerisque fermentum dui faucibus in. Leo duis ut diam quam nulla porttitor massa id neque. Vitae tortor condimentum lacinia quis vel eros. Velit euismod in pellentesque massa placerat duis ultricies lacus. и любой символ без пробелов Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dictum sit amet justo donec enim diam vulputate. Nunc faucibus a pellentesque sit amet. Quis enim lobortis scelerisque fermentum dui faucibus in. Leo duis ut diam quam nulla porttitor massa id neque. Vitae tortor condimentum lacinia quis vel eros. . I've figured out how to do it in regex101 here but was wondering if there's a shorter tr/sed/awk equivalent I can use in my bash shell. Something like file.txt

#обработка текста

Tan9


Рег
09 Sep, 2009

Тем
72

Постов
187

Баллов
587
  • 25, Oct 2024
  • #2

 
 
 $ make paranlneg
lex  -o lex.paranlneg.c paranlneg.l
egcc -O2 -pipe    -o paranlneg lex.paranlneg.c  -ll
rm -f lex.paranlneg.c
$ perl -E 'say "a\nb\n\nc\nd"' | ./paranlneg
a b

c d
$ 
 
has a paragraph mode via the %% [\n][\n]+ { printf("%s", yytext); } \n { int c = input(); /* TODO book docs say this should return EOF on EOF ?? */ if (c == 0) { putchar('\n'); yyterminate(); } else { printf(" %c", c); } } <<EOF>> { putchar('\n'); yyterminate(); } %% int main(int argc, char *argv[]) { return yylex(); } EOF флаг, поэтому, если мы заменим все внутренние символы новой строки вашего lex with a space:

(?!\Z)

$ wc -l input 7 input $ perl -00 -pe 's/\n(?!\Z)/ /g' input | wc -l 3 $ bit is to not replace the newlines at the end of each paragraph, thus preserving the paragraph boundaries.

Другой вариант: input . This reveals a few tricky points, notably how to handle perlrun и всегда ли включать последнюю новую строку (как требует POSIX) и то, что вы определяете как абзац: ровно две новые строки или любое другое число?

-00

Вероятно, нужно больше тестов, чем

perl
 

Lera1


Рег
18 Mar, 2006

Тем
81

Постов
202

Баллов
627
  • 25, Oct 2024
  • #3

Похоже на: Ответ @thrig на основе Perl но используя GNU Awk:

 
 fmt -w1000 file.txt
 

Для быстрого решения вы можете использовать Coreutils. fmt utility with a suitably large width value:

$ gawk -vRS= '{$1=$1; printf $0 RT}' file.txt Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dictum sit amet justo donec enim diam vulputate. Nunc faucibus a pellentesque sit amet. Quis enim lobortis scelerisque fermentum dui faucibus in. Leo duis ut diam quam nulla porttitor massa id neque. Vitae tortor condimentum lacinia quis vel eros.

(хотя по умолчанию после каждой точки добавляется двойной пробел).

 

Vladlencom


Рег
15 Jun, 2014

Тем
69

Постов
207

Баллов
592
  • 25, Oct 2024
  • #4

ГНУ

 
 $ sed --null-data 's/\([^[:space:]]\)\n\([^[:space:]]\)/\1 \2/g' file.txt
 
based approach:

Вы можете использовать sed to replace sed персонажи с sed characters, then use $ tr '\n' '\0' <file.txt | sed 's/\o000\{2,\}/\n\n/g' | tr '\0' ' ' | sed --null-data 's/ $/\n/' изменять последовательности из двух или более последовательных <NUL> characters into a double tr символ, затем используйте <newline> to replace remaining <NUL> символы с пробелами:

sed

Вот, последний <NUL> is only needed to substitute the final remaining space with a new line.

В качестве альтернативы (и более кратко) вы можете проинструктировать <newline> to treat your file as a sequence of null-terminated lines (that is, tr считает это одной строкой) и заменяет одним пробелом все вхождения одной новой строки, перед которой и за которой следует символ, не являющийся пробелом:

sed

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

 

Goldfish75


Рег
25 Sep, 2009

Тем
72

Постов
191

Баллов
551
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно