Обойти ограничение обратной ссылки sed от 1 до 9 - PullRequest
16 голосов
/ 30 ноября 2010

В руководстве sed четко указано, что доступные обратные ссылки, доступные для замещающей строки в замене, пронумерованы от \ 1 до \ 9.Я пытаюсь проанализировать файл журнала, который имеет 10 полей.

У меня сформировано регулярное выражение, но десятый матч (и все после) недоступно.

Есть ли у кого-нибудь элегантный способ обойти это ограничение в KSH (или любом другом языке, который, возможно, я смогу перенести в сценарии оболочки)?

Ответы [ 5 ]

13 голосов
/ 30 ноября 2010

Можете ли вы использовать perl -pe 's/(match)(str)/$2$1/g;' вместо sed? Способ обойти ограничение обратных ссылок - использовать что-то отличное от sed.

Кроме того, я полагаю, вы могли бы выполнить замену в два этапа, но я не знаю ваш шаблон, поэтому я не могу вам помочь, как.

5 голосов
/ 18 июня 2013

Разделить поток с -e, если замененные элементы находятся в группе, с которой вы их разбили.Когда я разделил дату, чтобы перестроить дату и время в строку из 14 цифр, мне пришлось разделить поток на 3 раза.

echo "created: 02/05/2013 16:14:49" |  sed -e 's/^\([[:alpha:]]*: \)//' -e 's/\([0-9]\{2\}\)\(\/\)\([0-9]\{2\}\)\(\/\)\([0-9]\{4\}\)\( \)/\5\1\3/' -e 's/\([0-9]\{2\}\)\(\:\)\([0-9]\{2\}\)\(\:\)\([0-9]\{2\}\)/\1\3\5/'

20130205161449

3 голосов
/ 30 ноября 2010

Вы запрашиваете решение сценария оболочки - это означает, что вы не ограничены использованием просто sed, правильно? Большинство оболочек поддерживают массивы, так что, возможно, вы можете проанализировать строку в переменной массива оболочки? При необходимости вы можете даже проанализировать одну и ту же строку несколько раз, извлекая разные биты информации на каждом проходе.

Будет ли это делать?

2 голосов
/ 29 марта 2017

Если у вас есть GNU awk, вы можете делать вещи с гораздо большим контролем. Для этого вам понадобится конструкция match(source,/regex/,array).

Пример:

Пример ввода для теста:

 echo "$x"
p1=aaa,p2=bb,p3=cc,p4=dd,p5=ee,p6=ff,p7=gg,p8=hh,p9=ii,p10=jj

sed отлично работает до \9:

echo $x |sed -r 's/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+)(.*)/\1 \2 \3 \4 \5 \6 \7 \8 \9/'
aaa bb cc dd ee ff gg hh ii

sed сломан, когда \10 добавлен, считается \1 + 0.

echo $x |sed -r 's/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+).*p10=([^,]+)(.*)/\1 \2 \3 \4 \5 \6 \7 \8 \9 \10/'
aaa bb cc dd ee ff gg hh ii aaa0

awk для спасения, когда добавлена ​​любая обратная ссылка больше 9. Здесь добавлено 10-е упоминание:

echo "$x" |awk '{match($0,/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+).*p10=([^,]+)(.*)/,a);print a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10]}'
aaa bb cc dd ee ff gg hh ii jj
1 голос
/ 27 февраля 2013

Рассмотрим решение, которое не требует использования обратных ссылок на регулярные выражения.Например, если у вас есть простой разделитель полей, используйте split или даже используйте awk для обработки вместо perl.

...