2

私は現在、設定ファイルを解析するためのPerlスクリプトを書いています。構文は次のとおりです

{command parameter1 parameter2}

ここで、2番目のパラメーターはオプションです。{そもそも、との間のコンテンツを抽出したいだけです}。このコードを使用しています

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}

角かっこで囲まれた内容を返しますが、2番目のパラメーターが存在する可能性があるため、引用符なしでパラメーターを区別するのは困難になりました。

のような他の文字列

{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"}

両方とも引用符で囲みます。最初の文字を「chmod770...」に書き換えると、再び機能します。

ここで問題を引き起こす原因は何ですか?

4

1 に答える 1

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これは、正しく入力することも解析することも非常に簡単です(ただし、最後の例は間違っていると確信しています!)

于 2012-08-27T08:53:19.877 に答える