
У меня есть этот простой код
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! очень здорово!