Este é um problema mais complicado do que parece, mas não além
a capacidade de regex. Para analisá-lo: Uma linha inteira consiste em
texto não comentado opcionalmente seguido por texto comentado. O que pode
aparecem em texto não comentado:
- Qualquer caractere diferente de
\
, #
, '
, "
-
\
seguido por qualquer caractere
- Uma string entre aspas, que começa e termina com
"
e pode conter
- A) qualquer caractere diferente de
\
ou "
- B)
\
seguido por qualquer caractere
- Uma string entre aspas, que começa e termina com
'
e pode conter
- qualquer caractere diferente de
'
(A diferença no tratamento dos dois tipos de citações é baseada em como
shells unix lidar com isso - ajustar a gosto)
Traduzindo isso diretamente para o regex, você quer:
s/^([non comment])[comment]$//
non comment = ([^\"'#]|\.|"([^\"]|\.)*"|'[^']*')*
(11111111|222|3(AAAAAA|BBB)33|4444444)*
comment = #.*
Therefore
s/^(([^\"'#]|\.|"([^\"]|\.)*"|'[^']*')*)#.*$//
Para um sed
regex, você precisa de mais barras invertidas, antes dos caracteres (
, |
e )
:
s/^\(\([^\"'#]\|\.\|"\([^\"]\|\.\)*"\|'[^']*'\)*\)#.*$//
E o bash precisa de cotações adicionais:
sed 's/^\(\([^\"'\''#]\|\.\|"\([^\"]\|\.\)*"\|'\''[^'\'']*'\''\)*\)#.*$//'
EDIT: Eu não tinha percebido que grep -o
existia até que eu vi a resposta do @StéphaneChazelas. O mesmo regex principal pode ser adaptado a essa abordagem, e egrep permite que você evite fazer a maioria das barras invertidas extras:
grep -Eo '^([^\"'\''#]|\.|"([^\"]|\.)*"|'\''[^'\'']*'\'')*'
grep -Eo "^([^\\\"'#]|\\.|\"([^\\\"]|\\.)*\"|'[^']*')*"
Ambos são idênticos em significado (e fortuitamente são do mesmo tamanho), são apenas diferentes abordagens para citar shell - eu pessoalmente prefiro a primeira abordagem porque citação simples é o único caractere que eu tenho que me preocupar, mas você pode ache o segundo mais legível, e ele se parece muito com o que você escreveria em outras linguagens de programação.
Uma ressalva é que o regex não sabe o que fazer com linhas que
contém citações não correspondentes. Eles não corresponderão ao regex, portanto, o comando sed não removerá nada, enquanto o comando grep removerá tudo.