it-swarm.com.de

Warum funktioniert sed nicht?

Ich habe HTML-Code, aus dem ich Links extrahieren möchte. Im Moment sieht die Datei so aus.

website.com/path/to/file/234432517.gif" width="620">
website.com/path/to/file/143743e53.gif" width="620">
website.com/path/to/file/123473232.gif" width="620">
website.com/path/to/file/634132317.gif" width="620">
website.com/path/to/file/432432173.gif" width="620">

Ich versuche, sed zu verwenden, um den " width="620"> aus allen Zeilen zu entfernen. Hier ist mein Sed-Code:

Sudo sed -i "s/\"\swidth\=\"\d+\"\>//g" output

Warum funktioniert das nicht? Alles, was ich google, führt zu etwas Code, der so aussieht, aber aus irgendeinem Grund nicht funktioniert.

5
Andrew Pullins

Da Sie die PCRE-Syntax (Perl Compatible Regular Expressions) verwenden und sed dies nicht versteht, werden standardmäßig Basic Regular Expressions (BRE) verwendet. Es kennt weder \s noch \d. Sie entkommen auch allen Arten von Dingen, die nicht entkommen müssen (weder der \= noch der \> tun etwas Nützliches), während Sie nicht entkommen müssen (+ bedeutet nur, dass Sie das Symbol + in BRE brauchen) \+ für "eins oder mehr".

Dies sollte tun, was Sie brauchen:

sed 's/" width="[0-9]\+">//g' file

Oder mit Extended Regular Expressions:

sed -E 's/"\s*width="[0-9]+">//g' file

Schließlich können Sie in der Regel niesed -i verwenden, ohne zuerst zu testen, ob der -i funktioniert, oder, falls Sie dies tun, zumindest -i.bak verwenden (-i mit einem beliebigen Text wird dies tun), um einen zu erstellen Sicherung.

19
terdon

Hier ist meine sed Lösung:

sed -E 's/(.*)" width="[0-9]+">/\1/' filename

Und als Alternative zu sed schlage ich vor, grep zu verwenden, um Daten aus einer Datei zu extrahieren:

Das würde für Sie funktionieren:

grep -o "website.*\.gif" filename

Und wie von Terdon vorgeschlagen, ist hier eine Vorausschau-Lösung mit grep:

grep -Po '.*(?="\swidth="\d*">)' filename

Auch cut ist eine gute Option in Ihrer Situation:

cut -f1 -d'"' filename
4
Ravexina

Oder für einen kürzeren Austausch einfach alles entfernen, nachdem gif

sed 's/gif.*/gif/' file

Der .* stimmt mit einer beliebigen Anzahl von Zeichen überein, solange das, was Sie verlieren möchten, immer hinter einer Zeichenfolge steht, die Sie finden können ... und keine anderen Instanzen in einer Zeile vorhanden sind. Es würde website.com/path/to/gif/xyz.gif" width..." mit dem früheren gif übereinstimmen, also zu unerwünschten Ergebnissen führen.

1
matt

Da Sie einen Perl-regulären Ausdruck geschrieben haben, können Sie einfach Perl verwenden. Sie können einen einzeiligen Befehl Perl anstelle eines Befehls sed eingeben. Dann müssen Sie Ihren regulären Ausdruck nicht in einen anderen Dialekt übersetzen und auf keine der praktischen Funktionen von Perl verzichten.

  • Verwenden Sie anstelle von sed -iPerl -pi -e.
  • Verwenden Sie anstelle von sed -i.bakPerl -pi.bak -e. (Sie können ein beliebiges Suffix verwenden, es muss nicht .bak sein.)

Wie terdon sagt, ist es bei -i am besten, ein Suffix anzugeben, damit eine Sicherungsdatei erstellt wird, zumindest wenn Sie nicht den gleichen Befehl ohne -i ausgeführt haben. (Dies gilt für Perl ebenso wie für sed.)

So sieht es mit Ihrem spezifischen Befehl aus:

Perl -pi.bak -e "s/\"\swidth\=\"\d+\"\>//g" file

Wenn Sie einfache Anführungszeichen um das Such- und Ersetzungsmuster verwenden, müssen Sie die darin enthaltenen "-Zeichen nicht umgehen oder die interessante Regeln für doppelt zitierten Text. Dies erleichtert das Schreiben und Lesen. (Das ist nicht spezifisch für Perl; Ihr sed-Befehl könnte ähnlich vereinfacht werden.) Dieser Befehl ist äquivalent:

Perl -pi.bak -e 's/"\swidth\="\d+"\>//g' file

Mit einem dieser Befehle werden die Zeilen in Ihrem Beispiel geändert in:

website.com/path/to/file/234432517.gif
website.com/path/to/file/143743e53.gif
website.com/path/to/file/123473232.gif
website.com/path/to/file/634132317.gif
website.com/path/to/file/432432173.gif

Weiterführende Literatur:

0
Eliah Kagan