Как превратить линейный поток в непрерывный поток?

Вопрос или проблема

В моем постоянном стремлении разумно подвести файлы .po под контроль версий git, я написал этот скрипт для использования в diff и filter-clean:
msgcat --no-location --no-wrap --sort-output - | msgattrib --no-obsolete - | grep -Ev '^"POT-Creation-Date|^"PO-Revision-Date|^"Last-Translator|^"X-Generator'

Каждый из шагов выполняет одну важную функцию:

  1. Рефакторинг и не относящиеся к делу изменения кода бесконечно меняют местоположение исходного кода и порядок записи. Этот вызов msgcat нормализует их, так что файлы commit-tet не содержат этих изменений.
  2. Устаревшие записи удваивают размер наборов изменений каждый раз, когда изменяется msgid. У нас есть контроль версий -> этот вызов msgattrib удаляет их.
  3. Эти поля в записи метаданных файла .po изменяются каждый раз, когда кто-то редактирует его с помощью специализированного инструмента – у нас есть контроль версий -> этот вызов grep удаляет их.

Теперь возникло еще одно препятствие. Обратите внимание на --no-wrap спереди? Это не работает.
Более того, обертка нестабильна: в каждую нечетную фиксацию кто-то получает слово, перевернутое между строками без человеческих изменений.
Кроме того, связанный инструмент Poedit тоже имеет настройку “Wrap at”, отключение которой тоже не работает. (Потому что он делегирует это инструментам gettext, в этом нет сюрпризов. Но это означает, что у меня нет способа нормализовать файлы “только в этот раз” и покончить с этим. – Поэтому я использую git filter в первую очередь.)

Очень хорошо, я подумал и протестировал этот вызов для их удаления: sed -z -e 's/\"\n\"//'.
Это для объединения любых обернутых строк в ‘msgid’ и ‘msgstr’, таким образом инструменты могут оборачивать их, как хотят, каждый день по-разному, мне все равно.

  • Это работает отдельно: sed -z -e 's/\"\n\"//' test.po выводит ожидаемый результат.
  • Это работает, когда передается через cat: cat test.po | sed -z -e 's/\"\n\"//' выводит ожидаемый результат.
  • Когда добавляется в существующий скрипт, однако, шаг sed не имеет эффекта.

Похоже, что он получает ввод построчно. Я пытался поставить это перед grep без улучшения, и я не могу переместить это перед двумя другими, поскольку msgcat и msgattrib имеют свою проблему “Мне нравится, чтобы мои обертки были случайными”, которая подтолкнула ко всей этой проблеме с самого начала.

Могу ли я потоково передавать вывод grep, или более общим образом вывод на основе строкового конвейера, чтобы мой потоковый редактор мог выполнять свои задачи?

(Примечание: на этом сайте есть много ответов, которые говорят “sed не может этого сделать” – но sed специально разработан так, чтобы не заботиться о разрывax строк, так что это звучит как дезинформация. Из мануала:

Sed это редактор потока. Редактор потока используется для выполнения базовых текстовых преобразований на входном потоке (файле или входе из конвейера). […] sed работает, делая только один проход по входным данным[.]

выделение мое

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

Конвейеры всегда представляют собой непрерывные потоки – читатель, как правило, не может различить границы записи. (Исходная программа может решить буферизовать свой вывод и сбрасывать его построчно или блоками, но это редко различимо.)

Похоже, что у вас противоположная проблема, т.е. -z фактически говорит ‘sed’ рассматривать весь его ввод как одну очень длинную “строку”, и по умолчанию его операция s// заменяет только первое совпадение в этой “строке”.

Добавьте параметр /g, чтобы изменить это:

msgattrib | grep | sed -z -e 's/\"\n\"//g'

Ответ или решение

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

Понимание проблемы

Ваша ситуация заключается в необходимости обрабатывать .po файлы так, чтобы они были корректно нормализованы для git, с учётом того, что различные инструменты могут изменять форматирование текста. Вы сталкиваетесь с тем, что команды sed -z -e 's/\"\n\"//' работают в изоляции, но не эффективно функционируют в цепочке команд из-за особенностей буферизации и обработки строк.

Потоковая обработка с sed

Как вы правильно заметили, sed в режиме -z рассматривает весь ввод как единичную строку. Однако по умолчанию замена производится только для первого найденного совпадения. Чтобы обеспечить замену для всех совпадений в этом единичном "потоке", нужно использовать флаг /g, который указывает на необходимость глобальной замены.

Пример команды

Вот как ваша команда будет выглядеть с применением флага /g:

msgcat --no-location --no-wrap --sort-output - | msgattrib --no-obsolete - | grep -Ev '^"POT-Creation-Date|^"PO-Revision-Date|^"Last-Translator|^"X-Generator' | sed -z -e 's/\"\n\"//g'

Объяснение этапов

  1. msgcat — нормализует порядок строк и убирает ненужные местоположения, чтобы изменения не сказывались на вашем git-репозитории.
  2. msgattrib — удаляет устаревшие записи, что позволяет сократить размер изменений при редактировании.
  3. grep — устраняет строки метаданных, которые не имеют отношения к содержимому переводов.
  4. sed — объединяет строки, которые были разделены, чтобы обеспечить непрерывный поток текста для дальнейшей обработки.

Практические рекомендации

  • Убедитесь, что ваши команды правильно обрабатывают вывод. Попробуйте тестировать каждую команду по отдельности, чтобы убедиться в её работе, и затем объединяйте.
  • Следите за кодировкой файлов и верными символами конца строки, которые могут влиять на результат.

Заключение

В результате последовательного применения вышеупомянутых команд вы можете успешно обрабатывать .po файлы, избегая проблем с переносом строк при трансформации текста. Этот подход не только решает вашу текущую задачу, но и создает основу для устойчивого процесса управления версиями с использованием git.

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

Оцените материал
Добавить комментарий

Капча загружается...