MATCH1.MATCH2 {
always same MATCH3
}
Todos os três MATCH
devem corresponder.
entrada:
foo.bar {
always same bus
}
1.2 {
always same 3
}
a.b {
always same c
}
i.ii {
always same iii
}
b.2 {
always same c
}
1.2 {
always same b
}
digamos que eu queira excluir 1
e a entrada MATCH(es) (do nome até a chave de 2
fechamento )3
}
saída:
foo.bar {
always same bus
}
a.b {
always same c
}
i.ii {
always same iii
}
b.2 {
always same c
}
1.2 {
always same b
}
Tentei várias abordagens, sed
mas nenhuma delas me levou perto:
sed "/$match1\.$match2/{/$match3//d;}" ./input
sed "/^$match1\.$match2 {/,/^always same $match3/d" ./input
# ...
Eu tive muita dificuldade com o fato de haver duas linhas que precisam ser correspondidas. Tentei adicionar \n
e .*
no meio, mas sem sucesso.
Aqui está o que usei para excluir a entrada correspondendo apenas à primeira linha, se isso ajudar:
sed "/^$match1\.$match2 {/,/^}/d" ./input # no match3
Expressão Regex
(?s)$match1.$match2 \{[^\{\}]*$match3\n\}\n
Observações:
(?s)
corresponde ao restante do padrão com os seguintes sinalizadores efetivos:s
.s
modificador: linha única. Ponto corresponde a caracteres de nova linha.[^\{\}]
corresponde a todos os caracteres não{
e}
.sed
Se você não estiver restrito a usar
sed
, você pode tentar usar/ajustar o seguinte script Python3.Script Python3
Saída
Não tenho certeza se essa é a maneira correta de fazer isso, mas consegui com a ajuda do @continuous-improvement:
Comentários e correções serão apreciados!
Supondo que as variáveis de shell
m1
,m2
em3
sejam definidas como expressões regulares válidas, ased
expressão tenta encontrar linhas que correspondam a^$m1\.$m1 {$
. Quando tal linha é encontrada, ela anexa a linha seguinte ao buffer usandoN
. Se o buffer agora corresponder$m3$
(incluindo o espaço inicial antes do valor da variável), uma linha adicional é lida do arquivo e o buffer é descartado, omitindo toda a seção de três linhas da saída.Uma abordagem diferente é sempre ler uma seção inteira de três linhas e então fazer uma única correspondência no buffer de várias linhas:
Usando qualquer awk, independentemente de suas variáveis de correspondência
m1
, etc. conterem ou não metacaracteres regexp, pois ele está apenas fazendo comparações literais de strings:Eu usaria
perl
em vez desed
:-p
é osed
modo em que a expressão (passada para-e
) é avaliada para cada registro de entrada.-0<octal>
altera o separador de registro de entrada, aqui777
sendo maior que qualquer valor de byte possível, toda a entrada será tratada como um todo.s{regex}{replacement}flags
comflags
term
for multiline for^
e$
para corresponder no início e no fim de cada linha no assunto, não apenas no início e no fim do assunto,g
para substituir todas as ocorrências,x
para permitir espaços em branco na expressão regular para torná-la mais legível.replacement
aqui vazioregex
tem:\h
para qualquer espaço em branco horizontal (em particular, não inclui quebra de linha).\s
para qualquer espaço em branco, incluindo nova linha (talvez você queira substituir alguns dos\s
s por\h
se não quiser que a nova linha seja correspondida, como se não quiser permitir uma quebra de linha entrealways
esame
)\Q$ENV{matchN}\E
insere a variável de ambiente correspondente no regexp, mas\Q
é utada (até o\E
nd) para que seja tratada como uma string fixa e não um regexp (o que importaria para valores$matchN
como4.5
onde.
é um operador regexp)Isso removeria tudo de
Se você precisar remover também:
Altere para:
Incorporar a expansão (pelo shell)
$shell_var
nosed
código como você faz introduz vulnerabilidades de execução de comandos arbitrários e é melhor evitá-la.Isso não se aplica ao
perl
acima, pois é uma$perl_variable
referência do Perl em seu operador regexp, não o shell expandindo uma variável do shell no código a ser interpretado pelo Perl.