Por que o sed não está funcionando?

4

Eu tenho alguns HTML dos quais estou tentando extrair links. No momento, o arquivo é assim.

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

Estou tentando usar sed para remover o " width="620"> de todas as linhas. Aqui está o meu código sed:

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

Por que isso não está funcionando? tudo o que eu google leva a algum código que se parece com isso, mas isso não funciona por algum motivo.

    
por Andrew Pullins 21.07.2017 / 14:36

4 respostas

17

Como você está usando a sintaxe PCRE (Expressões regulares compatíveis com Perl) e sed não entende isso, ela usa Basic Regular Expressions (BRE) por padrão. Não sabe nem \s nem \d . Você também está escapando de todos os tipos de coisas que não precisam ser escapadas (nem o \= nem o \> estão fazendo nada útil) enquanto não está escapando de coisas que precisam ser escapadas ( + significa apenas o símbolo + no BRE, você precisa de \+ para "um ou mais".

Isso deve fazer o que você precisa:

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

Ou usando expressões regulares estendidas:

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

Por fim, como regra geral, você nunca usa sed -i sem primeiro testar sem o -i para ter certeza de que funciona ou, se fizer isso, use pelo menos -i.bak ( -i com qualquer texto fará isso) para criar um backup.

    
por terdon 21.07.2017 / 14:47
4

Aqui está minha sed solution:

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

E, como alternativa ao sed , sugiro usar grep para extrair dados de um arquivo:

Isso funcionaria para você:

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

E, conforme sugerido por Terdon, aqui está uma solução de look ahead usando grep :

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

Além disso, cut é uma boa opção na sua situação:

cut -f1 -d'"' filename
    
por Ravexina 21.07.2017 / 14:51
1

Ou para uma troca mais curta, basta remover tudo depois de gif

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

O .* corresponde a qualquer número de qualquer caractere, desde que o que você queira perder seja sempre depois de uma string que você possa localizar ... e que não haja outras instâncias dela em uma linha. Ele corresponderia a website.com/path/to/gif/xyz.gif" width..." no gif anterior, portanto, dê resultados indesejados.

    
por matt 21.07.2017 / 17:06
0

Como você escreveu uma expressão regular Perl , é possível use o Perl . Você pode emitir um comando perl em uma linha, em vez de um sed comando. Então você não precisa traduzir sua expressão regular em um dialeto diferente, e você não precisa abrir mão de nenhum dos recursos úteis de Perl.

  • Em vez de sed -i , use perl -pi -e .
  • Em vez de sed -i.bak , use perl -pi.bak -e . (Você pode usar qualquer sufixo, não precisa ser .bak .)

Como terdon diz , com -i é melhor especificar um sufixo para que ele crie um arquivo de backup, pelo menos se você não tentou o mesmo comando sem -i primeiro. (Isso é tão verdadeiro com perl como com sed .)

Veja o que parece com o seu comando específico:

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

Se você usa aspas simples ao redor do padrão de pesquisa e substituição, não precisa escapar dos caracteres " que aparecem nele ou manter o controle dos regras interessantes para texto com aspas duplas. Isso facilitará a gravação e a leitura. (Isso não é específico para perl ; seu comando sed poderia ser similarmente simplificado.) Esse comando é equivalente:

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

Com um desses comandos, as linhas do seu exemplo são alteradas para:

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

Leitura adicional:

por Eliah Kagan 21.07.2017 / 21:41