我有一个源文件,我使用宏来进行日志记录。典型的日志记录行如下所示:
STDOUT_LOG(logDEBUG4) << "a single line log text" << aVariable;
还存在一些多行日志命令:
STDOUT_LOG(logDEBUG4)
<< bsd->sensorName
<< " trainMinValueInWin = " << value.trough
<< " trainMaxValueInWin = " << value.peak
<< " |";
我们的想法是获取日志字符串(无论是单行还是多行)并将它们放在宏的括号中。
通常最终结果如下:
STDOUT_LOG(logDEBUG4,"a single line log text" << aVariable);
或
STDOUT_LOG(logDEBUG4,
bsd->sensorName
<< " trainMinValueInWin = " << value.trough
<< " trainMaxValueInWin = " << value.peak
<< " |");
我正在尝试阅读与多行匹配相关的任何内容,包括perl中的while循环,/s
amd /m
运算符以及搜索和替换的潜在方法,但我距离正确匹配多行宏。我假设我需要/ s运算符以便&#34;。&#34;也匹配换行符,但我无法成功使用它。
模式的开头当然是&#34; STDOUT_LOG&#34;并且结束是第一次出现&#34;;&#34;然而很多行后来它出现了。
这种尝试
perl -ne 's/STDOUT_LOG\((.*?)\)(.*?)\;/STDOUT_LOG($1,$2)\;/gs; print;'
设法获取日志级别(&#34; logDEBUG4&#34;在这种情况下)是&#34;排序&#34;单行日志命令的OK,但是即使我最后使用了/ s,其余行的匹配也会失败。
如何解决此问题?我应该使用哪些其他操作员?那里有什么好的教程吗?最终是否有一个可以挽救这一天的perl命令?
编辑: 因为没有任何建议为我开箱即用(模式匹配失败,因此没有任何改变),我想知道这里是否涉及一些更新的功能。无论如何,我的perl版本是5.18.2。我试图在linux cli中运行命令,如下所示:
perl -ne 's/pattern/replace/gs; print;' <filename>
我希望我在这里做错了什么
答案 0 :(得分:1)
答案 1 :(得分:1)
$log
字符串包含整个日志,包含换行符和所有
$log =~ s/STDOUT_LOG\K \( ( [^)]+ ) \) ( [^;]+ );/($1,$2);/xs;
[^)]+
与第一个右括号匹配,同样[^;]+
也会转到第一个;
。您不需要也不需要/g
修饰符。 /x
允许空格以便于阅读。
\K
是positive lookbehind的一种特殊形式,它也会丢弃之前的所有匹配项。因此,用作断言之前的模式不受替换的影响。见in perlretut。这里不是必需的,但是如果你把它留下来,那么匹配就会消耗STDOUT_LOG
,所以它也需要在替换部分输入。它就这么干净了。
由于日志输入方式可能存在问题,因此这是一个完整的程序
use warnings 'all';
use strict;
my $logfile = 'log.txt';
my $log = do {
local $/;
open my $fh, '<', $logfile or die "Can't open $logfile: $!";
<$fh>;
};
# print $log;
$log =~ s/STDOUT_LOG\K \( ([^)]+) \) ([^;]+);/($1,$2);/xs;
print $log;
do
块允许我们通过取消设置$logfile
(或{{1}将 slurp 整个文件$log
添加到$INPUT_RECORD_SEPARATOR
变量中} {},在local的块内。请参阅perlvar中的讨论。
如果这是用单线
来完成的$/
perl -0777 -pe 's/STDOUT_LOG\K \( ([^)]+) \) ([^;]+);/($1,$2);/xs;' log.txt
使整个文件变为-0777
,默认情况下对其进行替换。处理完每一行后,$_
也会打印-p
(这里我们只有一行)。有关命令行开关,请参阅perlrun; $_
请参阅General Variables in perlvar。
这两个都假设所显示的日志示例(单行或多行)独立存在,只需要处理一个日志字符串。为简单起见,我将其放在文件$_
中并将其从该文件中读取到脚本中的log.txt
变量中,然后读入单行中的$log
。
答案 2 :(得分:0)
这是一种方法:
use Modern::Perl;
my @lines = (
'STDOUT_LOG(logDEBUG4) << "a single line log text" << aVariable;',
' STDOUT_LOG(logDEBUG4)
<< bsd->sensorName
<< " trainMinValueInWin = " << value.trough
<< " trainMaxValueInWin = " << value.peak
<< " |";'
);
for (@lines) {
s/(STDOUT_LOG\(.*?)\)(\s*)<<(.*?);/$1, $2$3);/gs;
say;
}
<强>输出:强>
STDOUT_LOG(logDEBUG4, "a single line log text" << aVariable);
STDOUT_LOG(logDEBUG4,
bsd->sensorName
<< " trainMinValueInWin = " << value.trough
<< " trainMaxValueInWin = " << value.peak
<< " |");
答案 3 :(得分:0)
最终成功完成我想要的命令如下:
gh-pages
这对于#Federico Piazza&#34;的回答很有说服力。和&#34; zdim&#34;。您会注意到我在&#34; STDOUT_LOG&#34;之前添加了#34; STDOUT_LOG&#34;在前面的位置真的非常符合我想要的大量源文件。我注意到,为了正确匹配,必须在正则表达式的末尾包含perl -0777pne 's/STDOUT_LOG\((.*?)\)(.*?)<<(.*?);/STDOUT_LOG\(\1\,\2\3\);/gs' sensor.cpp
运算符,还要在perl可执行文件中添加/s
标志。
有关运行时perl可执行标志的说明,请参阅perlrun