Как искать любой член списка значений с помощью sed - PullRequest
1 голос
/ 18 апреля 2020

не знаю, как правильно задать вопрос, но вот пример использования:

  • У меня есть файл ~ 18GB XML (OpenStreetMap); ~ 250M строк
  • В файле ~ 250 записей, которые нарушают работу, которые повреждают набор данных
  • Удаляемые записи являются многострочными и имеют форму: <way id="foo">... <\way>
  • У меня есть те идентификаторы в файле bad_ways

Я мог бы написать для l oop и циклически перебирать кучу sed операторов вроде этого:

sed -i.bu '/<way id="1_bad_way_entry".*/,/<\/way>/d' in.xml

, но .. . Для этого требуется ~ 250 циклов при записи файла 18G и записи на диск и т. д. c., что в настоящее время занимает около 18 минут на цикл (вращающийся диск ... исправит это в ближайшее время на коммутационных машинах. Обновление: SSD улучшится примерно до 6,5 мин за цикл).

Можно ли попросить sed сопоставить любую запись в bad_ways и сделать это за 1 проход?

Или есть Есть ли лучшие инструменты для этого, чем sed? Заранее спасибо!

1 Ответ

0 голосов
/ 18 апреля 2020

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

(Примечание: в дальнейшем я использую опцию sed * -E, чтобы сохранить обратную косую черту; если вы не используете вам нужно создать сценарий sed, включив при необходимости обратную косую черту.)

Например, предположим, что файл bad_ways выглядит следующим образом:

one
two
three

и что huge_file выглядит следующим образом:

everything starts with a zero, then one is next, then two, then three, finally four

вы можете выполнить sh задачу с помощью следующей команды, чтобы заменить все шаблоны, перечисленные в bad_ways, на XXX:

sed -E 's/'"$(sed -zE 's/\n([^$])/|\1/g' bad_ways)"'/XXX/g' huge_file

Тогда вывод будет

everything starts with a zero, then XXX is next, then XXX, then XXX, finally four

Как видите, сценарий sed, который действует на huge_file, состоит из объединения трех строк:

  1. s/ это одинарные кавычки (вы всегда должны предпочитать одинарные кавычки, если только вам не нужны двойные кавычки, как в 2).
  2. вывод sed -zE 's/\n([^$])/|\1/g' bad_ways, который в двойных кавычках разрешает подстановку команд и генерирует one|two|three
  3. /XXX/g.

Все это приводит к строке s/one|two|three/XXX/g.

* 1 043 * Это не совсем та строка, которая вам нужна для вашего скрипта, но я надеюсь, что этот ответ покажет вам пример , как использовать подстановку команд $(…) и соответствующие кавычки с ' и " для создания команда (sed, awk или что-то еще) динамически .

Оглядываясь назад, этот ответ основан на той же «философии», что и ответ, связанный с комментарием. Однако я не временно сохраняю скрипт в файл. Это может иметь второстепенное значение, если сам скрипт небольшой (и он небольшой, в зависимости от вашего описания).

...