LINUX.ORG.RU

Замена в длинной строке.

 , ,


0

2

Приветствую. Имеется текстовый файл с одной строкой длиной в десяток миллионов символов. Нужно найти в строке набор символов вида:
«nw758» X type:test=«string»><test:q>00</test:q>
и заменить на:
«nw758» X type:test=«string»><test:q>99</test:q>
Проблема в том, что X - это произвольный набор символов, но длина его всегда от 1 до 935 символов (если не учитывать что длина ограничена 935 символами то могут измениться те данные, которые не нужно было изменять). Как это реализовать используя sed? Или в данном случае лучше посмотреть в сторону другого инструмента?

А в чём проблема? .+ или там .{1,935} не подходит?

anonymous
()

Если у вас «00</test:q>» всегда одинаковое - можно просто убрать количество этих символов в конце строки да добавить что нужно.

micronekodesu ★★★
()

Попробуй:

sed -e 's/\<test\:q\>00\<\/test\:q\>/\<test\:q\>99\<\/test\:q\>/g' file.in>file.out

kickass
()

Если вопрос вызван сомнениями вида «а потянет ли sed такую длинную строку», то стоит просто проверить. А так, можно awk взять и вручную всё сделать

Deleted
()
Ответ на: комментарий от r3lgar

Да, нужно именно набор символов, начинающийся с

«nw758»
и в котором дальше идёт 1-935 символов а за ним
 type:test=«string»><test:q>
. Т.е. не просто текст в тэге, а текст в тэге, которому предшествует определённый текст, часть которого известна, часть неизвестна.

zarat03
() автор топика
Ответ на: комментарий от kickass

Оно заменит ВСЕ вхождения, ибо найдёт первый \1, последний \5, и заменит все \4 (который вообще матчить не было смысла) на 99. Кури на тему жадности sed.

r3lgar ★★★★★
()

Регулярные выражения такое не могут. PCRE должен с его хитрыми группами с предпросмотром, но это ненастоящие регэкспы.
sed, насколько помню, не умеет в pcre. Поэтому либо perl, либо инстумент, который может более мощные грамматики, чем регексп.

anonymous
()
Ответ на: комментарий от zarat03

Опять не понял, эти «1-935 символов» надо менять или они остаются? В любом случае, у вас известно количество символов в начале строки и в конце строки, между ними - то, что нужно заменить, я не могу понять почему не хотите плясать от этого.

А вообще - если у вас там xml то возьмите нормальный парсер.

micronekodesu ★★★
()
Ответ на: комментарий от micronekodesu

возьмите нормальный парсер

Ну вот, взял и всё испортил.

anonymous
()
Ответ на: комментарий от kickass

Проблема в том, что строка сдесь символы не должна быть больше 935 символов. Т.е. если между nw758 и test:q > ~1000 символов, то значение 00 не надо изменять. В Вашем примере это не учитывается (проверял на реальном файле).

zarat03
() автор топика
Ответ на: комментарий от micronekodesu

Все символы, кроме 00 остаются. 00 меняется на 99.

zarat03
() автор топика
Ответ на: комментарий от r3lgar

Оно заменит ВСЕ вхождения, ибо найдёт первый \1, последний \5, и заменит все \4 (который вообще матчить не было смысла) на 99. Кури на тему жадности sed.

Жадность ограничена. Как только в маску попадет type:test=«string»><test:q>, сработает 3 match и закроется 2, дальше заработает 4, ограниченный 5 маской и своей. Он закроется, далее 5. Как только в 5 попадет <\/test:q> тоже закроется. Т.к. вся фигня собрана, всё вылетает в >file.out с заменой чего надо.

Если есть ещё символы, то всё заного, т.к. /g

Или я ошибаюсь?

Если вместо sed -e написать perl -pe то будет также работать.

kickass
()
Ответ на: комментарий от zarat03

Ну да, над этим надо думать. Тут счётчик какой-то должен быть.

kickass
()
Ответ на: комментарий от kickass

Или я ошибаюсь?

Ошибаешься. Логику sed я тебе описал, ты её даже процитировал, но я снова выделю важный кусок:

первый \1, последний \5

Так как у ТСа файл — это всего одна бесконечно длинная строка.

r3lgar ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.