Используем sed с этим регулярным выражением:
message=$(echo "$path" | sed -E 's/(.+pattern[0-9][0-9]*).+/\1/')
С этим выражением получаются такие строки:
/lol/pattern03657/qsd/qsd/pattern0001/qsd/
будет заменено на:
/lol/pattern03657/qsd/qsd/pattern0001
тогда как я хотел бы, чтобы они были:
/lol/pattern03657/
Я думал, что sed заменит только первое вхождение, но, похоже, этого не происходит. Что мне нужно изменить, чтобы мой код вел себя таким образом?
решение1
Это потому , что *
, +
являются жадными квантификаторами, будут пытаться сопоставить как можно больше
$ echo '/lol/pattern03657/qsd/qsd/pattern0001/qsd/' | sed -E 's/(.+pattern[0-9][0-9]*).+/\1/'
/lol/pattern03657/qsd/qsd/pattern0001
perl
имеет нежадный квантификатор, добавляя ?
к+
$ echo '/lol/pattern03657/qsd/qsd/pattern0001/qsd/' | perl -pe 's/(.+?pattern\d+\/).+/\1/'
/lol/pattern03657/
или используйте grep
с pcre
опцией, если доступно
$ echo '/lol/pattern03657/qsd/qsd/pattern0001/qsd/' | grep -oP '^.+?pattern\d+/'
/lol/pattern03657/
Один из обходных путей sed
— это если вы знаете, где находится ваша строка. Например:
$ echo '/lol/pattern03657/qsd/qsd/pattern0001/qsd/' | sed -E 's|^(/[^/]+/pattern[0-9][0-9]*/).+|\1|'
/lol/pattern03657/
Здесь, с начала строки, один набор /text/
предшествует строке