
更新:
- 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 -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
程式碼只是將替換應用於所有不以字元開頭的行#
。