替换包含换行符的替换模式而不会中断流

时间:2013-11-08 19:34:48

标签: regex bash sed

我有一些我不得不使用的Plesk服务器,我编写了一个脚本来通过CLI处理备份。麻烦的是,如果Plesk备份工具在备份域时遇到问题,那么输出有用的信息的唯一方法就是使用详细标志运行整个备份作业。麻烦的是,它会在作业运行时每秒输出一次工具Domains [0/1]\n,如果它运行了一个小时,那么你有3600行无用的信息推送有用的信息超出缓冲区。例如:

Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
Domains [0/1]
-------------- Start print backup log hire --------------
<?xml version="1.0" encoding="UTF-8"?>
  <execution-result status="success" log-location="/usr/local/psa/PMM/sessions/2013-11-08-114156.109/migration.result"/>
-------------- End print backup log hire --------------

我一直在尝试做的是创建一个命令来管理这个,只需用哈希标记替换\nDomains [\d+/\d+],所以上面会变成:

Domains [0/1]########
-------------- Start print backup log hire --------------
<?xml version="1.0" encoding="UTF-8"?>
  <execution-result status="success" log-location="/usr/local/psa/PMM/sessions/2013-11-08-114156.109/migration.result"/>
-------------- End print backup log hire --------------

我找到了使用sed的{​​{1}}标记的方法,如Nsed ':a;N;$!ba;s:\nDomains \[[0-9]\+/[0-9]\+\]:#:g'的一些fudgery,但这会导致整个输出被缓冲并输出仅在备份脚本完成后才生成。

如何让这个替代品在流中工作,这样我仍然可以获得实时状态输出?

有问题的命令是:

tr

编辑:我还想出了一个简短的测试脚本来生成相关文本而不运行十几个备份:

ssh ${server} sudo ${pbackup} domains-name -v --output-file=${ftp_spec} $domain 2>&1 | \
    sed ':a;N;$!ba;s:\nDomains \[0/1\]:X:g'

3 个答案:

答案 0 :(得分:1)

我认为编写自己的小工具可能是一个好主意,而我的首选语言是PHP。它并不漂亮,但是如果你对匹配和替换单个尾随换行符感兴趣,它就能完成工作。

<?php
if( $argc != 3 ) {
    echo "Bad args";
    exit(1);
} else if( ! $in = fopen('php://stdin', 'r') ) {
    echo "Could not open stdin.\n";
    exit(1);
}
while( $line = fgets($in) ) {
    $oline = preg_replace($argv[1], $argv[2], $line);
    if( is_null($oline) ) {
        echo "PCRE Error.";
        exit(1);
    } else { echo $oline; }
}
fclose($in);

,它被调用如:

ssh ${server} sudo ${pbackup} domains-name -v --output-file=${ftp_spec} $domain 2>&1 | \
    php streamedit.php ':Domains \[\d+/\d+\]\n:' '#'

并生成输出:

#######-------------- Start print backup log hire --------------
<?xml version="1.0" encoding="UTF-8"?>
  <execution-result status="success" log-location="/usr/local/psa/PMM/sessions/2013-11-08-142159.357/migration.result"/>
-------------- End print backup log hire --------------

这不是我想要的,但它完成了工作。

如果有人有不同/更好的解决方案,我非常愿意试一试。

答案 1 :(得分:0)

据我所知,如果没有换行,就无法输出任何东西。你可以编写一个sed脚本,当你想要保留一行时输出指定数量的哈希值和换行符。您当前的脚本不会执行此操作,而只是读取整个输入,然后才进行编辑。

如果您不需要#-signs,可以使用

| fgrep -v 'Domains [0/1]'

简单地忽略这些行。

答案 2 :(得分:0)

| sed -n -u "/Domains \[0\/1\]/ !p"

-u是sed的流版本,sed工作到第一个EOF,但在给出结果之前不缓冲整个结果