Ich habe eine Datei mit mehreren Zeichenfolgen, die aus einem HTML-formatierten Text stammen. Sie enthalten daher einige HTML-Sequenzen, die in einer Konsolenoberfläche nicht gut aussehen. Hier ist ein Beispiel:
Text1™
[Text®2]
Text:3
Ich versuche, alles zwischen & und ; zu entfernen, sodass der Text wieder lesbar ist, etwa wie folgt:
Text1
Text2
Text3
Ich versuche eigentlich, sed zu verwenden, um die zusätzlichen Zeichen zu entfernen:
sed 's#&*;##g' <file>
Das Problem besteht darin, dass nur das ; aus den Textzeichenfolgen entfernt wird.
Die Frage ist dann, wie der Regex-Ausdruck codiert werden sollte, um die zusätzliche Kette zu entfernen:&#[1-9]+;
Antwort1
Ihr regulärer Ausdruck
sed 's#&*;##g' <file>
tut nicht das, was Sie denken. Das *
Zeichen ist ein Multiplikator, der besagt, dass das vorhergehende Zeichen 0 oder mehr Mal wiederholt wird. Das vorhergehende Zeichen ist &
, daher würde dies z. B. mit &&&;
und ;
( &
steht 0 Mal vor ;
! Dies ist das, was in Ihren Testfällen übereinstimmt), aber nicht mit dem, was Sie in diesem Fall wollen.
Sie müssen angeben "beliebigZeichen“ vor dem Multiplikator, der durch einen einzelnen Punkt dargestellt wird, .
.
$ echo 'Text:3' | sed 's#&.*;##g'
Text3
Das war das erste Problem. Das zweite ist das Konzept des sogenannten „gierigen“ Matchings: Es sed
wird zuerst gesucht &
und dann versucht, den größten String zu finden, den es finden kann. Wenn Sie mehrere HTML-Entitäten in einer Zeile haben, wäre das ein Problem, weil:
$ echo 'Text:3 and some more text å and end' | sed 's#&.*;##g'
Text and end
Wenn Sie eine Korrektur im Kontext sehen möchten sed
, können Sie nach dem Endzeichen der Entität suchen, indem Sie eine beliebige Anzahl von "nicht ;
" vor einem Abschluss, ;
indem Sie Folgendes tun:
$ echo 'Text:3 and some more text å and end' | sed 's#&[^;]*;##g'
Text3 and some more text and end
Sie werden weiterhin Probleme mit der legitimen Verwendung des Et-Zeichens ( &
) im Text haben (also, &
es ist die wirklich „legitime“ Verwendung, aber die reale Welt ist nicht immer so analysierbar wie die ideale) und mit zu vielen Übereinstimmungen, aber dies erklärt, warum es sed
sich so verhält, wie es sich verhält.
Antwort2
Ist es nicht besser, die Codes durch die tatsächlichen Zeichen zu ersetzen?
echo 'Text1™
[Text®2]
Text:3' | perl -C -pe 's/&#([^;]*)/chr$1/eg'
Ausgabe:
Text1™;
[;Text®;2];
Text:;3