web-dev-qa-db-fra.com

Pourquoi sed ne fonctionne-t-il pas?

J'ai un peu de HTML dont j'essaie d'extraire des liens. En ce moment, le fichier ressemble à ceci.

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">

J'essaie d'utiliser sed pour supprimer le " width="620"> de toutes les lignes. Voici mon code sed:

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

Pourquoi ça ne marche pas? Tout ce que je recherche sur Google conduit à un code qui ressemble à ceci, mais cela ne fonctionne pas pour une raison quelconque.

5
Andrew Pullins

Comme vous utilisez la syntaxe PCRE (Perl Compatible Regular Expressions) et que sed ne comprend pas cela, il utilise les expressions régulières de base (BRE) par défaut. Il ne connaît ni \s ni \d. Vous échappez également à toutes sortes de choses qui n'ont pas besoin d'être échappées (ni le \= ni le \> ne font rien d'utile) tout en n'échappant pas à des choses qui doivent être échappées (+ signifie simplement le symbole + dans BRE, vous avez besoin \+ pour "un ou plusieurs".

Cela devrait faire ce dont vous avez besoin:

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

Ou, en utilisant des expressions régulières étendues:

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

Enfin, en règle générale, vous jamais utilisez sed -i sans d'abord tester sans le -i pour vous assurer de son bon fonctionnement ou, si vous le faites, utilisez au moins -i.bak (le -i avec n'importe quel texte le fera) pour créer un sauvegarde.

18
terdon

Voici ma solution sed:

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

Et en guise d'alternative à sed, je suggère d'utiliser grep pour extraire les données d'un fichier:

Cela fonctionnerait pour vous:

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

Et comme l'a suggéré terdon, voici une solution de prévisualisation utilisant grep:

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

cut est également une bonne option dans votre cas:

cut -f1 -d'"' filename
4
Ravexina

Ou, pour un échange plus court, supprimez tout simplement après gif

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

Le .* correspond à n’importe quel nombre de caractères, tant que vous voulez perdre, c’est toujours après une chaîne que vous pouvez localiser ... et qu’il n’y en a aucune autre instance dans une ligne. Il correspondrait à website.com/path/to/gif/xyz.gif" width..." sur le gif précédent, donnez donc des résultats non souhaités.

1
matt

Puisque vous avez écrit un Expression régulière Perl , vous pouvez simplement utiliser Perl . Vous pouvez émettre une commande Perl à la place d'une commande sed . Ensuite, vous n'avez pas à traduire votre expression régulière dans un dialecte différent et vous ne devez renoncer à aucune des fonctionnalités pratiques de Perl.

  • Au lieu de sed -i, utilisez Perl -pi -e.
  • Au lieu de sed -i.bak, utilisez Perl -pi.bak -e. (Vous pouvez utiliser n'importe quel suffixe, il n'est pas nécessaire que ce soit .bak.)

Comme terdon dit , avec -i, il est préférable de spécifier un suffixe afin de créer un fichier de sauvegarde, du moins si vous n'avez pas essayé la même commande sans -i au préalable. (Ceci est aussi vrai avec Perl qu'avec sed.)

Voici à quoi cela ressemble avec votre commande spécifique:

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

Si vous utilisez des guillemets simples autour du motif de recherche et de remplacement, vous n'êtes pas obligé d'échapper aux caractères " qui y figurent ou de garder la trace du shell règles intéressantes pour le texte entre doubles guillemets. Cela facilitera l'écriture et la lecture. (Ce n'est pas spécifique à Perl; votre commande sed pourrait être simplifiée de la même manière.) Cette commande est équivalente:

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

Avec l'une de ces commandes, les lignes de votre exemple sont modifiées en:

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

Lectures supplémentaires:

0
Eliah Kagan