Может быть, Perl Negative Lookbehind с обходом переменной длины?

Может быть, Perl Negative Lookbehind с обходом переменной длины?

У меня есть этот простой код

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

и я хочу, чтобы он заменил все параметры = 10, но не если им предшествует хэш в любом месте этой строки. например

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

Я знаю, что если я предоставлю

((?<!#\s*))

Я получаю сообщение об ошибке

В регулярном выражении не реализован просмотр назад переменной длины

Так есть ли способ выполнить эту задачу другими способами?

Спасибо

решение1

Вы можете сделать что-то вроде:

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

Идея в том, что #.*(который мы заменяем на себя) сожрёт все комментарии. А во второй части чередования мы ищем ваш шаблон (здесь parameter=...при условии, что ему не предшествует непробельный символ) в том, что осталось.

Другой подход заключается в использовании:

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

\Kустанавливает начало части для замены. mФлаг делает ^соответствие в начале каждой строки внутри темы.

Если они parameter=находятся только в начале строк (за которыми следуют необязательные пробелы), то это просто:

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

решение2

Ну, единственная альтернатива, которую я смог придумать, это:

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" 

Выход:

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

Нам нужно использовать '^(?!#+$)(\s*)'отрицательный просмотр вперед построчно. И он принимает переменные длины (может быть, потому что он не в многострочной строке? пока не знаю.)

Я наткнулся на эту идеюhttps://www.regextester.com/95226и наконец-то заработало.

Я узнал сегодня что-то новое. Надеюсь, это будет вам полезно!

PS. мы также могли бы использовать простой вариант, ([^#]*)как предложилтердон https://unix.stackexchange.com/a/521512/354415кто предложил по сути ту же концепцию, что и здесь, но реализованную в одной строке на Perl! очень здорово!

Связанный контент