2010-11-30 11 views
14

Das sed-Handbuch besagt eindeutig, dass die verfügbaren Rückreferenzen, die für die Ersetzungszeichenfolge in einem Ersatz verfügbar sind, mit den Nummern \ 1 bis \ 9 nummeriert sind. Ich versuche, eine Protokolldatei mit 10 Feldern zu analysieren.Umgehung der sed-Rückverweisgrenze 1 bis 9

Ich habe die Regex dafür gebildet, aber die zehnte Übereinstimmung (und alles danach) ist nicht zugänglich.

Hat jemand eine elegante Möglichkeit, diese Einschränkung in KSH (oder einer anderen Sprache, die ich vielleicht an Shell-Skripte portieren kann) zu umgehen?

+2

Sie können ziemlich viel verwenden jede Skriptsprache, die Sie schreiben Einzeiler hierfür können. 'perl -pe 's/yourrexhere/$ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9 $ 10 /' ' –

+0

Es ist durchaus möglich, dass Sie eine einfachere Regex verwenden können, die nicht so viele Rückverweise benötigt. Wenn Sie Beispieldaten und ein Beispiel für die von Ihnen gewünschte Ausgabe anzeigen, können wir Ihnen wahrscheinlich einen einfacheren Weg zeigen. –

+1

klingt wie ein Job für 'awk' - Feld 10 ist' $ 10' –

Antwort

13

Können Sie Benutzer perl -pe 's/(match)(str)/$2$1/g;' anstelle von sed? Die Möglichkeit, die Rückreferenzgrenze zu umgehen, besteht darin, etwas anderes als sed zu verwenden.

Auch, ich nehme an, Sie könnten Ihren Ersatz in zwei Schritten tun, aber ich kenne Ihr Muster nicht, so kann ich Ihnen nicht helfen wie.

+0

Danke, das hat super funktioniert. Jetzt muss ich herausfinden, wie man Muster im laufenden Betrieb erzeugt und diesen Befehl von einem ksh-Skript aus ausführt, aber das ist eine Frage für einen anderen Tag. –

3

Sie fragen nach einer Shell-Skript-Lösung - das bedeutet, dass Sie nicht nur auf sed beschränkt sind, richtig? Die meisten Shells unterstützen Arrays, also können Sie die Zeile möglicherweise in eine Shell-Array-Variable zerlegen? Bei Bedarf können Sie die gleiche Zeile sogar mehrfach analysieren, um bei jedem Durchlauf verschiedene Informationen zu extrahieren.

Würde das tun?

1

Betrachten Sie eine Lösung, die die Verwendung von Rückverweisen für reguläre Ausdrücke nicht erfordert. Wenn Sie beispielsweise ein einfaches Feldtrennzeichen haben, verwenden Sie split oder verwenden Sie sogar awk für Ihre Verarbeitung anstelle von Perl.

3

Teilen Sie den Stream mit -e, solange die ersetzten Elemente in der Gruppe sind, mit der Sie sie teilen. Als ich eine Datumsaufteilung machte, um das Datum in eine 14-stellige Zeichenfolge umzuordnen, musste ich den Stream dreimal aufteilen.

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

Wenn Sie GNU awk haben, können Sie Dinge tun, mit viel mehr Kontrolle. Dazu benötigen Sie match(source,/regex/,array) Konstrukt.

Beispiel:

Probenaufgabe für den Test:

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

sed fein bis \9 funktioniert:

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 brach, als \10 hinzugefügt wird, ist es als \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 zu retten, wenn eine Rückbeziehung mehr als 9 zugegeben wird, zugegeben. Hier 10. refrence angefügt:

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