【问题标题】:Perl: matching strings containing slash in quotation marksPerl:匹配在引号中包含斜线的字符串
【发布时间】:2012-08-27 08:23:17
【问题描述】:

我目前正在编写一个 Perl 脚本来解析一个配置文件。语法如下

{command parameter1 parameter2}

第二个参数是可选的。首先,我只想提取{} 之间的内容。我正在使用此代码

while (<FILE>) {
    chomp;
    unless ($_ =~ m/^\/\//) {
            $_ =~ /^\{(.*?)\}/s;
            print $1;
}

字符串将被进一步评估,而不是print 命令。我现在的问题是脚本停止使用某些字符串

只要参数周围有引号,脚本就可以工作。这个

{exec sed 's/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new}

将返回括号之间的内容,但由于可能有第二个参数,现在很难区分没有引号的参数

其他字符串,如

{exec "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak"}
{exec "/etc/init.d/ssh reload"}

完美运行,包括引号。

但是现在,引号中的字符串,包括斜杠或加号(可能还有其他),此时只会冻结 perl 脚本:

{exec "chmod +x /root/setSSHTimer.sh"}
{exec "sed 's/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new"}

都带引号。将第一个重写为“chmod 770 ...”时,它再次起作用。

任何想法是什么导致了这里的问题?

【问题讨论】:

  • 老实说,我建议使用更强大的配置设置,例如 JSON 或 XML。
  • 正如 Jack 所说,如果您在解析自己的设计以获取配置语法时遇到问题,那么就出现了严重错误。该文件可以看起来像您想要的那样,并且您遇到的问题可以通过将命令和参数放在单独的行上来解决,例如,用一个空行来分隔它们。您是否考虑了包含{} 字符的参数?

标签: regex perl


【解决方案1】:

问题不在于您显示的代码,它只是提取了{...} 大括号之间的所有内容,而在于进一步评估的代码。如果您遇到问题,请发布此内容

请注意,您可以通过使用不同的分隔符来避免在正则表达式中转义斜杠,并且像 next if m|^//| 这样的行可以避免将循环的所有其余部分放在 if 语句中

解析命令行很尴尬 - 因为您必须处理包含在 "..."'...' 引号中的参数,允许在参数中使用转义引号 - 但可能

这是一个似乎可以正确解析所有示例数据的程序

use strict;
use warnings;

while (<DATA>) {

  next if m|^//| or not /\S/;

  if (/^\{(.*?)\}/) {
    my $command = $1;
    my @fields = $command =~ /'(?:\\'|[^'])*'|"(?:\\"|[^"])*"|\S+/g;
    print join(' ', map "[$_]", @fields), "\n";
  }
}

__DATA__
{exec sed 's/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new'}
{exec "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak"}
{exec "/etc/init.d/ssh reload"}
{exec "chmod +x /root/setSSHTimer.sh"}
{exec "sed 's/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new"}

输出

[exec] [sed] ['s/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new']
[exec] ["cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak"]
[exec] ["/etc/init.d/ssh reload"]
[exec] ["chmod +x /root/setSSHTimer.sh"]
[exec] ["sed 's/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new"]

更新

这种配置格式至少应该分成几行,以便可以删除引号和转义符,例如

exec
sed
s/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/ /etc/ssh/sshd_config > /etc/ssh/sshd_config.new

exec
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

exec
/etc/init.d/ssh reload

exec
chmod +x /root/setSSHTimer.sh

exec
sed
s/ClientAliveInterval\ 300/ClientAliveInterval\ 1800/\' /etc/ssh/sshd_config > /etc/ssh/sshd_config.new

正确输入和解析都非常容易(尽管我确信您最后的sed 示例是错误的!)

【讨论】:

  • 您好,感谢您的完美回答!从那里我能够将它集成到我的脚本中并成功解析所有内容。谢谢!不幸的是,我无法将您的答案表示为“有用”...
  • 请记住我对您的问题的评论。这是一个糟糕的配置语法设计
  • Borodin:感谢您的反馈,我知道设计远非完美。这是一个供内部(很少)使用的小脚本。这对于我们将要使用的内容已经足够了,而且我永远不会向公众发布它,还有更多的安全“功能”;)但是再次感谢您的帮助!
  • 我的意思是你在为自己做事。我向你保证,配置变得更加复杂,而当前的设计几乎无法满足要求
  • @waza-ari:我非常同意鲍罗丁的观点。你真的应该重新考虑一下。就像拔牙一样——一开始很痛,但后来你会感觉好些,如果你不拔牙,随着时间的推移,它只会增加压力和疼痛。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 2017-01-26
  • 1970-01-01
  • 2013-04-01
  • 2022-07-06
  • 1970-01-01
  • 2015-10-01
相关资源
最近更新 更多