Perl:在引号中匹配包含斜杠的字符串

时间:2012-08-27 08:23:17

标签: regex perl

我正在编写一个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}

将返回括号之间的内容,但由于可能存在第二个参数,现在很难在没有qoutation标记的情况下区分参数

其他字符串,如

{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 ...”时,它再次起作用。

任何想法导致问题的原因在哪里?

1 个答案:

答案 0 :(得分:3)

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

请注意,您可以通过使用不同的分隔符来避免在正则表达式中转义斜杠,而像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示例是错误的!)