Perl Negative Lookbehind com desvio de comprimento variável, talvez?

Perl Negative Lookbehind com desvio de comprimento variável, talvez?

Eu tenho esse código simples

perl -we 'my $file= "
    #    parameter=10
#    parameter=10
# parameter=10
    parameter=10
parameter=10
"; $file=~ s/((?<!# ))\s*parameter\s*=.*/parameter=replaced/g; print(":$file:\n")'

e quero substituir todos os parâmetros = 10, mas não se for precedido por um hash em qualquer lugar dessa linha. por exemplo

        #    parameter=10
#    parameter=10
# parameter=10
        parameter=replaced
parameter=replaced

eu sei que se eu fornecer um

((?<!#\s*))

Eu recebo um erro

Lookbehind de comprimento variável não implementado em regex

Então, existe uma maneira de realizar a tarefa por outros meios?

Obrigado

Responder1

Você pode fazer algo como:

s/#.*|((?<!\S)parameter\h*=.*)/$1 ? "parameter=replaced" : $&/ge;

A ideia é que o #.*(que substituímos por si mesmo) elimine todos os comentários. E na segunda parte da alternância, procuramos o seu padrão (aqui parameter=...desde que não seja precedido por um espaço que não seja em branco) no que resta.

Outra abordagem é usar:

s/^[^#\n]*\K(?!<\S)parameter\h*=.*/parameter=replaced/gm;

\Kdefine o início da peça a ser substituída. A mbandeira ^corresponde no início de cada linha dentro do assunto.

Se eles parameter=forem encontrados apenas no início das linhas (seguidos de espaços em branco opcionais), então isso é apenas:

s/^\h*\Kparameter\h*=.*/parameter=replaced/gm;

Responder2

Bem, a única alternativa que consegui encontrar é esta:

FILESECTION="\
        #    parameter=10
#    parameter=10
#  parameter=10
        parameter=10
parameter=10
"

newfile=''
while IFS= read -r line ; 
    do 

    SECTIONFIXED=$( perl -le '$file=$ARGV[0]; $file=~ s/^(?!#+$)(\s*)(parameter\s*=.*)/parameter=replaced/g; print("$file\n");' "${line}" ; ) 
    newfile=$( printf "${newfile}\n${SECTIONFIXED}\n" )  
done <<< "$FILESECTION"

echo "$newfile" 

Saída:

        #    parameter=10
#    parameter=10
#  parameter=10
parameter=replaced
parameter=replaced

Temos que usar '^(?!#+$)(\s*)'lookahead negativo linha por linha. E aceita comprimentos variáveis ​​(talvez porque não esteja em uma string multilinha? ainda não sei).

Me deparei com essa ideiahttps://www.regextester.com/95226e finalmente consegui.

Eu aprendi algo novo hoje. Espero que você ache isso útil!

PS. também poderíamos usar um simples ([^#]*)como sugerido porterdon https://unix.stackexchange.com/a/521512/354415que sugeriu basicamente o mesmo conceito que aqui, mas implementado em um perl one liner! muito legal !

informação relacionada