У меня есть файл, содержащий текст в абзацах (строки с текстом, разделенным одной или несколькими пустыми строками). Я хотел бы изменить порядок абзацев (то есть последний абзац станет первым, ...), предпочтительно с помощью sed.
Я ищу команду sed, которая будет делать с файлом абзацев, что tac
будет делать с файлом строк.
источник
Возможно, есть способ сделать это
sed
, но я сомневаюсь, что это будет просто. Вот как я бы сделал это в Perl:Это работает, потому что определение разделителя входной записи как нулевого символа (
-00
) указывает Perl работать в режиме абзаца. Определение абзаца 1 в Perl точно соответствует вашему определению.1 Посмотрите под заголовком
Other values for $/
источник
Если ваши абзацы всегда разделены одной пустой строкой:
Это довольно легко увидеть , как это работает , если вы разбить его на куски и работать
sed '/^$/s/^/\x02/' infile
потомsed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\n
и так далее ...Если ваши абзацы разделены одной или несколькими пустыми строками, например
и вы хотите изменить порядок абзацев, но сохранив порядок «пустых блоков», вы можете прочитать файл дважды:
1-й: превратить абзацы в одну строку (удаляя пустые блоки между ними) и повернуть их вспять и
2-й: превратить пустые блоки в отдельные строки «индексируют» количество пустых строк в каждом блоке (и удаляют непустые строки),
затем
paste
результаты и обрабатывают выходные данные для восстановления новых строк:какие выводы:
Если вы не возражаете против дополнительной строки в выводе, вы можете оставить последнюю
sed
:Они предполагают, что первая и последняя строки не пусты (и нет
\x02
,\x03
или\x04
во входных данных).источник
Вы МОЖЕТЕ сделать это с одним экземпляром
sed
; трубы не нужны. Посколькуsed
только один проход по документу и часть файла, необходимая в качестве начала вывода, находится в конце файла, потребуется удерживать весь файл в памяти внутриsed
(в области удержания) - так что это может плохо масштабируется. Но это точно отвечает на вопрос:Если нет завершающего символа новой строки, все равно работает нормально. Если есть один завершающий символ новой строки, он подавляется в выходных данных (т. Е. В выходных данных не будет ведущего символа новой строки). Если на входе (например) 5 завершающих строк новой строки, на выходе будет 4 ведущих строки новой строки.
Пробелы между абзацами сохраняются.
Пробелы в пустой строке НЕ рассматриваются как разрыв абзаца, но это особенность, а не ошибка. :)
Вы также можете сделать это как гораздо менее читаемый однострочный:
Хотя это работает только с GNU
sed
. (Обратите внимание на хитрое использование обратных ссылок для выполненияs/$/\n/
. Без этого он не был бы буквальным однострочным, поскольку содержал бы обратную косую черту.)источник
G;h
. Вы могли бы упомянуть что-то об ограничениях ввода или подобное.sed
рукой GNU , но версия скрипта определенно сохраняет пробелы между абзацами. Я только что проверил это на вашем входе. Вы тестировали версию скрипта?Это должно сохранить интервал между абзацами (будучи более читабельным, чем
sed
:)). Хотя, реквизит devnull для потрясающего ответа.источник