【问题标题】:How can a name in an INI file be updated using a one-liner?如何使用单行更新 INI 文件中的名称?
【发布时间】:2011-08-04 12:51:42
【问题描述】:

使用 Perl 单行正则表达式命令替换 INI 文件的特定部分中的值?

我想将“Margin Top”值 1 替换为 0。该部分必须是“[Pagebar Button Skin]”。

在 RegExr 中尝试使用 global 和 dotall 的 "(\[Pagebar Button Skin\].+?Margin Top\s+?=\s+?)(1)" 后,我能够使用 " 将值替换为 0 $10”或“$1 0”。

不幸的是,当我运行我的命令时它不起作用:

perl.exe -i.bak -pe "s/(\[Pagebar Button Skin\].+?Margin Top\s+?=\s+?)(1)/$1 0/g" test.txt

这是我的 test.txt 文件中的“[Pagebar Button Skin]”部分:

[Pagebar Button Skin]
Type                        = BoxStretch
Tile Center                 = pagebar/top/inactive.png
StretchBorder               = 12
Margin Top                  = 1
Margin Right                = -5
Margin Left                 = -5
Margin Bottom               = 0
Padding Left                = 12
Padding Top                 = 5
Padding Right               = 9
Padding Bottom              = 6
Spacing                     = 3
Text Color                  = #111111

编辑:

我必须创建一个 Perl 脚本才能使正则表达式工作。也许 Perl 不喜欢我的 Windows 环境。

命令:

perl.exe skin.pl skin.ini

皮肤.pl:

$/ = undef; # Setting $/ to undef causes <FILE> to read the whole file into a single string.

# Store filename from argument
my $filename = shift;

# Open the file as read only and then store the file text into a string.
open(FILE, "<", $filename) || die "Could not open $filename\n";
my $text = <FILE>;
close(FILE);

# Re-open the file as writable and then overwrite it with the replaced text.
open(FILE, "+>", $filename) || die "Could not open $filename\n";
$text =~ s/(\[Pagebar\s+?Button\s+?Skin\].+?Margin\s+?Top\s+?=\s+?)(1)/${1}0/sg;
#print $text; # Print the text to screen
print {FILE} $text; # Print the text to the file
close(FILE);

【问题讨论】:

    标签: regex perl replace ini


    【解决方案1】:

    沿线尝试一些东西

    perl -pe 'if (/^\s*\[Pagebar Button Skin\]/../^\s*\[/) { s/(Margin\s+Top\s*=\s*)1/${1}0/ }'
    

    这将仅在页面栏部分的开头和下一个部分之间应用替换。此外,您可以使用一些 INI 模块,将文件作为结构读入 perl,更改您想要的内容并将其写出。取决于哪个更适合您的需求。

    【讨论】:

    • 谢谢,我不知道我可以用大括号做“${1}0”。顺便问一下,你的线路被切断了吗?
    • 已更正,不知道为什么被切断了。
    【解决方案2】:

    由于ini文件通常是段落模式,你可以试试:

    perl -p00 -e '/Pagebar Button Skin/ && s/(Margin Top.*=)\s*\d/$1 0/' file.ini
    

    输出:

    [Pagebar Button Skin]
    Type                        = BoxStretch
    Tile Center                 = pagebar/top/inactive.png
    StretchBorder               = 12
    Margin Top                  = 0
    Margin Right                = -5
    Margin Left                 = -5
    Margin Bottom               = 0
    Padding Left                = 12
    Padding Top                 = 5
    Padding Right               = 9
    Padding Bottom              = 6
    Spacing                     = 3
    Text Color                  = #111111
    

    对结果满意后,将 -i.bak 添加到单行中

    【讨论】:

    • 有效!这一篇回答了问题!我只需要使用双引号而不是单引号:“在 -e 第 1 行的 EOF 之前的任何地方都找不到字符串终止符“'”。”
    【解决方案3】:

    使用像Config::Tiny 这样的专用模块来解析配置文件。使用它的单线:

    perl -MConfig::Tiny -we '$file = shift; $config = Config::Tiny->read($file); $config->{"Pagebar Button Skin"}->{"Margin Top"} = 0; $config->write($file)' test.txt
    

    【讨论】:

    • 这行得通。但是,Config::Tiny 会在写入文件后删除空格,这可能是不可取的。我必须创建一个 Perl 脚本才能使正则表达式工作。也许 Perl 不喜欢我的 Windows 环境。
    • XP1:为什么要保留空白?据我所知,INI 脚本解析器应该忽略namevalue 之间的空格。
    • 是的,解析器会忽略空格,但我只是不想过多地更改文件,因为删除了很多空格,文件看起来会非常不同,并且更难比较。
    【解决方案4】:

    不要使用正则表达式。使用一个模块。 CPAN 有Config::INIConfig::IniFiles

    【讨论】:

    • 我将无法在单行命令中使用该模块。对吗?
    • XP1:您可以使用-M-m 切换到use 单行中的模块。见perldoc perlrun
    猜你喜欢
    • 2011-03-29
    • 1970-01-01
    • 2016-02-04
    • 2020-07-17
    • 2015-08-15
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 2019-10-04
    相关资源
    最近更新 更多