我有这个简单的代码
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")'
我希望它替换所有parameter=10,但如果它前面有该行任何地方的散列,则不替换。例如
# parameter=10
# parameter=10
# parameter=10
parameter=replaced
parameter=replaced
我知道如果我提供
((?<!#\s*))
我收到一个错误
正则表达式中未实现可变长度lookbehind
那么有没有办法通过其他方式来完成任务呢?
谢谢
答案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终于开始了。
我今天学了些新东西。希望你觉得这个有用!
附言。我们还可以使用一个简单的([^#]*)
建议特登 https://unix.stackexchange.com/a/521512/354415谁提出了与此处基本相同的概念,但在 Perl Oneliner 中实现!很不错 !