2010-11-30 3 views
14

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

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

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

+2

Вы можете использовать практически любой язык сценариев, который позволяет писать для этого однострочные. `perl -pe 's/yourregexhere/$ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9 $ 10 /'` – 2010-11-30 20:19:11

+0

Вполне возможно, что вы можете использовать более простое регулярное выражение, которому не нужно много обратных ссылок. Если вы покажете примерные данные и пример нужного результата, мы, возможно, покажем вам более простой способ. – 2010-11-30 21:10:06

ответ

13

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

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

3

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

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

1

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

3

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

Если у вас есть 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-й refrence:

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