
ОБНОВЛЯТЬ:
- РЕАЛЬНЫЙ ответ на этот МНОГОСТРОЧНЫЙ вопрос дал Стефанhttps://unix.stackexchange.com/a/521560/354415
- В качестве альтернативы можно воспользоваться кодом perl от Terdon, который представлен ниже: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
P.S. Если вам интересно узнать, как я продвигался в этом направлении, посмотрите здесь:Может быть, 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
просто применяет замену ко всем строкам, не начинающимся с #
символа.