Excluindo várias linhas de comentário HTML usando sed

0

Isso é o que eu criei, mas não funciona com várias linhas:

sed -i '/<!-- my comment -->.*<!-- \/my comment end -->/d' my_file

    
por Adam Silver 27.03.2016 / 23:45

1 resposta

1

Como sed em seu modo padrão opera linha a linha, uma abordagem (admitidamente ofuscada) seria substituir os caracteres de nova linha por algo mais (como o caractere NULL \x00 ) antes de alimentar o o conteúdo em sed :

tr '\n' '\x00' <my_file

sed , em seguida, vê o conteúdo como uma linha. No entanto,

sed -e 's/<!-- my comment -->.*<!-- \/my comment end -->//'

não funcionará devido à natureza de correspondência gulosa de sed . Poderíamos implementar uma correspondência não-ávida combinando tudo dentro do comentário até o primeiro caractere < , mas isso só funcionaria se os comentários HTML não tivessem permissão para conter < caracteres (e, em particular, outras tags HTML) , o que não podemos assumir.

Para resolver isso, converteremos a seqüência <! em um único caractere não usado em outro lugar no arquivo, para o qual podemos construir uma correspondência não-gulosa. Escolheremos o caractere especial \x01 para essa finalidade, que convertemos de volta para <! após a correspondência não desejada:

sed -e $'s/<!/\x01/g' -e $'s/\x01-- my comment -->[^\x01]*\x01-- \/my comment end -->//g'

(observe o uso da sintaxe do shell $'' em vez de '' para passar o caractere de byte único literal \ x01 para sed )

Em um terceiro estágio, os caracteres NULL são convertidos em novas linhas:

tr '\x00' '\n'

E, finalmente, as linhas vazias são suprimidas por outra invocação de sed :

sed -e '/^$/d'

Em resumo,

tr '\n' '\x00' <my_file |sed -e $'s/<!/\x01/g' -e $'s/\x01-- my comment -->[^\x01]*\x01-- \/my comment end -->//g' |tr '\x00' '\n'|sed -e '/^$/d'

Existem soluções mais elegantes se você optar por usar ferramentas diferentes ( awk ou perl one-liners) em vez de sed , como:

perl -0pe 's/<!-- my comment -->.*?<!-- \/my comment end -->//gs' my_file

    
por 28.03.2016 / 00:27

Tags