更新:
- Stephane 在这里给出了这个多行问题的真正答案https://unix.stackexchange.com/a/521560/354415
- 或者使用 Terdon 的 perl 逐行查看如下:https://unix.stackexchange.com/a/521512/354415
- 或者我自己在此处逐行使用 IFS:https://unix.stackexchange.com/a/521550/354415
这是我的新玩具:
问题是我希望它仅匹配参数前面没有 #\s* 的行。
请不要提供替代代码,例如 sed 等。使用 perl
perl -we 'my $file= "parameter=9
# parameter=10
parameter=10
"; $file=~ s/.*((?<!^# ))parameter\s*=.*/parameter=replaced/g; print(":$file:\n")'
预期产出
parameter=replaced
# parameter=10
parameter=replaced
PS如果您有兴趣了解我的进展情况,请看这里:Perl Negative Lookbehind 可能带有可变长度绕过?
答案1
由于您选择将多行字符串作为单个变量传递,这会变得复杂。将其转换为数组要容易得多,因此您可以s///
以最简单的形式使用运算符。试试这个:您说您对代码改进不感兴趣,但为了帮助未来的用户,这里是您编写的内容的简化版本,它也避免了对非环境变量使用 ALLCAPS 的不良做法:
newparameter='parameter=replaced'
filesection='
parameter=9
# parameter=10
parameter=10
'
matchparamperl='^([^#]*)parameter\s*=.*'
sectionfixed=$( perl -le '
@lines=split(/\n/,$ARGV[0]);
s/$ARGV[1]/$1$ARGV[2]/g for @lines;
print join "\n", @lines
' "$filesection" "$matchparamperl" "$newparameter")
echo "$sectionfixed"
这将返回:
$ echo "$sectionfixed"
parameter=replaced
# parameter=10
parameter=replaced
或者,短一点:
sectionfixed=$( perl -le '
do{
s/$ARGV[1]/$1$ARGV[2]/g; print
} for split(/\n/,$ARGV[0])
' "$filesection" "$matchparamperl" "$newparameter")
答案2
perl -we 'my $file= "parameter=9
# parameter=10
parameter=10
"; $file=~ s/.*((?<!# ))parameter\s*=.*/parameter=replaced/g; print(":$file:\n")'
这就是它的完成方式)))
输出:
parameter=replaced
# parameter=10
parameter=replaced
称为负向回顾 http://www.blackwasp.co.uk/RegexLookahead.aspx
感谢库萨拉南达提供这个想法。
我绝对不会想到这一点。
答案3
contents='
parameter=9
# parameter=10
parameter=10
'
sed '/^#/!s/parameter[[:blank:]]*=.*/parameter=replaced/' <<<"$contents"
输出:
parameter=replaced
# parameter=10
parameter=replaced
该sed
代码只是将替换应用于所有不以字符开头的行#
。