Обойти ограничение обратных ссылок sed от \1 до \9

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

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

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


person Steve M    schedule 30.11.2010    source источник
comment
Вы можете использовать практически любой язык сценариев, который позволяет вам писать однострочники для этого. perl -pe 's/yourregexhere/$1$2$3$4$5$6$7$8$9$10/'   -  person Anon.    schedule 30.11.2010
comment
Вполне возможно, что вы можете использовать более простое регулярное выражение, которое не требует большого количества обратных ссылок. Если вы покажете некоторые образцы данных и пример желаемого вывода, мы, вероятно, сможем показать вам более простой способ.   -  person Dennis Williamson    schedule 01.12.2010
comment
похоже на работу для awk -- поле 10 – это $10   -  person glenn jackman    schedule 01.12.2010


Ответы (5)


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

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

person robert    schedule 30.11.2010
comment
спасибо, это сработало отлично. теперь мне нужно выяснить, как генерировать шаблоны на лету и запускать эту команду из сценария ksh, но это вопрос для другого дня. - person Steve M; 01.12.2010

Разделите поток с помощью -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

person hanz    schedule 18.06.2013
comment
Приятно знать, что вы можете разделить его таким образом, но в вашем примере вам не нужно было захватывать части, которые вы выбрасывали. Следующее дает тот же эффект (-E позволяет убрать косую черту перед скобками): sed -E -e 's/[[:alpha:]]*: ([0-9]{2})\/([0-9]{2})\/([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/\3\1\2\4\5\6/' - person Kyle A; 01.08.2018

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

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

person zigdon    schedule 30.11.2010

Если у вас есть 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
person P....    schedule 29.03.2017

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

person fluffy    schedule 26.02.2013