Примечание См. Конец для версии, которая не зависит от порядка строк в [section]
Для входного файла точно , как показано
perl -pE'
/;\s*user\s*=\s*(.*)/ and $user = $1;
($u) = /^user\s*=\s*(.*)/;
s/^\s*displayName\s*=\s*\K.*/$user/ if $f;
$f = $u eq $user
' file
Показано в нескольких строках для удобства чтения, пояснения построчно:
Захватывает имя пользователя, которое будет использоваться для файла.Идет в начале в строках с ;
Захватить имя пользователя в разделе (user
начинается с строки) или $u
остается undef
Измените значение для displayName
--- если установлен флаг $f
(в предыдущей строке)
Установите для этого флага $f
значениерезультат сравнения: true (1), если $u
(установлено и) соответствует $user
Программа работает по строкам файла следующим образом:
в строке ;
устанавливается $user
, в то время как в других строках регулярное выражение не совпадает и ничего не происходит
в строках, начинающихся с user
(в разделах) задается имя пользователя раздела ($u
), в других строках $u
становится undef
изменение displayName
происходит, если $f
истинно, и это было установлено в предыдущей строке, если было установлено $u
и действительно было равно $user
- в противном случае это ложно.
, поэтому displayName
изменяется на строке, следующей за строкой user =
, и если на этой (предыдущей) строке пользователь $u
был равен найденному в начале ($user
).
Это свободно использует переменные, которые часто undef
и будут вызывать многочисленные предупреждения с -w
;вопреки моей практике, для простоты я опускаю это здесь (вместо тестирования с define
).
Код предполагает, что
определение имени пользователя предшествует его использованиюв строке, начинающейся с ;
(в начале)
в сечении строка user =
предшествует строке displayName =
--- но см. ниже
строки displayName
, которые идут позже, начинаются с фразы, перед ней ничего не стоит
user =
строки в разделах начинаются с user
изменить displayName =
только в разделе с именем пользователя, записанным в начале
Перезаписать входной файл (изменить его в-place ) добавить опцию -i
или -i.bak
, чтобы сохранить резервную копию.Чтобы создать новый файл с выходом перенаправления изменений, perl -wpe'...' file > new_file
Одно из необходимых и, возможно, запретительных допущений выше состоит в том, что строка user =
стоит перед строкой displayName =
, что в общем случае не являетсяправило в файле ini
.
Чтобы расслабиться, нам нужно сначала собрать строки для user
и displayName
для каждого раздела, и как только оба находятся на ручной работеэто и только потом записывать их
perl nE'
/;\s*user\s*=\s*(.*)/ and $user = $1;
if ( 2 == ( @k = keys %sec ) ) {
say "$_ = ", ( $sec{user} eq $user ? $user : $sec{$_} ) for @k;
%sec = ()
} else {
/^(user|displayName)\s*=\s*(.*)/ and $sec{$1} = $2
}
print $_ unless /^(user|displayName)/;
END {
say "$_ = ", ( $sec{user} eq $user ? $user : $sec{$_} ) for keys %sec
}
' file
(Создание этого более приятного, в частности, избавление от этого повторяющего код блока END, остается в качестве упражнения)
Если этот код нуждаетсяжить внутри скрипта bash и никаких дополнительных файлов на диске быть не может, пусть будет так;но в противном случае, пожалуйста, напишите это как хороший сценарий.