Perl匹配多行字符串并替换

时间:2015-06-15 04:48:46

标签: perl

我有一个位于远程主机中的文件。我想将该文件中的字符串cronExpression value="* 30 9 ? * MON-FRI"替换为cronExpression value="* $hour $min ? * MON-FRI"

输入文件为:test.properties

其内容如下:

<bean id="DisconnectCronTrigger"
class="org.springframework.scheduling.quartz.CronFactoryBean">
<property name="jobDetail" ref="delayDisconnectJobDetail" />
<property name="cronExpression" value="* 30 20 ? * MON-FRI" />
</bean>
<bean id="retryJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="retryMeterCommandJob" />
<property name="targetMethod" value="executeAll" />
</bean>
<bean id="retryCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="retryJobDetail" />
<property name="cronExpression" value="* 30 9 ? * MON-FRI" />
</bean>

我尝试了下面提到的代码但未能替换

%opts =(user => 'xxxxx',
password => '1234444');
my $ssh = Net::OpenSSH->new("$host", %opts);
$ssh->error and die "Can't ssh to $host: " . $ssh->error;

$pathFolder="perl -pi -e  'sm/\<property name=\"jobDetail\"    ref=\"delayDisconnectJobDetail\" \/\>.*?
            \<property name=\"cronExpression\" value=\"\* 30 20 \? \* MON\-FRI\" /\<property name=\"jobDetail\"    ref=\"delayDisconnectJobDetail\" \/\>.*?
            \<property name=\"cronExpression\" value=\"\* **40 10** \? \* MON\-FRI\"/gsm'     /test.properties";
$ssh->system("$pathFolder") or     die "remote command failed: " . $ssh->error;

<property name="targetMethod" value="executeAll" />
</bean>
<bean id="retryCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="retryJobDetail" />
<property name="cronExpression" value="* 30 9 ? * MON-FRI" />
</bean>

2 个答案:

答案 0 :(得分:2)

Perl中没有sm///substitution operators///match operatorm//。可能会给你一个语法错误。当你已经有一个Perl时,通过命令行执行此操作有点奇怪。

即使未安装在远程主机中,您也可以使用XML解析器。查看Object::Remote,它允许您运行Perl代码,甚至可以通过SSH在远程计算机上使用本地计算机上的Perl模块。 The author mst talks about that in the __END__ of everything

答案 1 :(得分:2)

你可以让Net :: OpenSSH为你做shell引用并摆脱你的一个问题。但是,在任何情况下,使用正则表达式来处理XML通常都是一个坏主意,因为XML文件中的任何微小更改都可能会破坏您的脚本。

由于您的文件似乎不是太大,只需使用scp复制到本地计算机,使用适当的XML处理模块XML::LibXML在本地执行任何所需的处理,最后将它们复制回远程机器:

use Net::OpenSSH;
use XML::LibXML;

my $hour = '...';
my $min = '...';

my $ssh = Net::OpenSSH->new($host,
                            user => 'xxxxx',
                            password => '1234444');
$ssh->error and die "Can't ssh to $host: " . $ssh->error;

$ssh->system(cp => '/test.properties', '/test.properties.bak'); # backup
$ssh->scp_get("/test.properties");

my $dom = XML::LibXML->load_xml(location => 'test.properties');
for my $ele ($dom->findnodes('/config/bean[property[@name="jobDetail" and
                                            @ref="delayDisconnectJobDetail"]]
                                          /property[@name="cronExpression"]')) {
    $ele->setAttribute(value => "* $hour $min ? * MON-FRI");
}

open my $out, '>', 'test.properties.new';
binmode $out;
$dom->toFH($out);

$ssh->scp_put('test.properties.new', '/test.properties');