搜索字符串

搜索字符串

如何搜索包含以下文本的文件,并且仅重定向输出,其中第三行有“Msg 208”,后跟“# name not found”?

文件文本:

[
DBCC upgrade_object: DEFAULT dc_1527463 upgraded successfully.
DBCC upgrade_object: Upgrading PROCEDURE tran_33
DBCC upgrade_object: There's a difference between the objectname tran_33 and the name tran_33 used in syscomments.
DBCC upgrade_object: Maybe the object was renamed using sp_rename.
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.itxxn_33', Line 40:
#old_33 not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
Msg 207, Level 16, State 4:
Server 'DEV_RP', Line 3:
Invalid column name 'eryCmt'.
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.yftran_33', Line 40:
bat not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.yftran_33', Line 40:
#wbat not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
]

示例 - 有效且应在输出中捕获:

{
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.itxxn_33', Line 40:
#old_33 not found. Specify owner.objectname or use sp_help to check whether the object exists 
}

示例 - 无效且不应在输出中捕获:

{
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.yftran_33', Line 40:
bat not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
}

答案1

假设空行是伪造的编辑工件:

注意:input2.txt是示例输入的编辑副本,删除了多余的换行符。

$ sed -E -e 's/^(Msg |\])/\n\1/; s/\[/[\n/' input2.txt  |
    perl -00 -l -n -e 'print if /^Msg 208.*^#.*not found/ms'
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.itxxn_33', Line 40:
#old_33 not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).

Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.yftran_33', Line 40:
#wbat not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).

这用于sed将输入转换为以 或 的每个实例开头的每一行的Msg段落。然后将的输出通过管道输送到以段落模式 ( )读取输入 ( ) 并打印该段落[]sedperl-n-00当且仅当它匹配正则表达式^Msg 208.*^#.*not found(使用 perl 的m修饰符将每个段落视为多行字符串,并使用s修饰符来允许.匹配换行符)。

“段落”是由一个或多个换行符分隔的一行或多行文本。

有关 perl 命令行选项的更多信息,请参阅man perlrun,有关 perl 正则表达式的更多信息,请参阅man perlre。有关在 Perl 脚本中使用正则表达式的教程,请参阅man perlretut

man perlre

m将匹配的字符串视为多行。也就是说,将 and 从匹配字符串第一行的开头和最后一行的结尾更改^$匹配字符串中每行的开头和结尾。

s将字符串视为单行。也就是说,更改.为匹配任何字符,甚至是换行符,通常它不会匹配。

一起使用时,/ms它们可以让.匹配任何字符,同时仍然允许^$分别匹配字符串中换行符之后和之前的字符。

顺便说一句,这本来可以完全在 Perl 中完成,但将sed输入转换为 Perl 的段落模式可以轻松处理的内容会更简单、更容易、更快。

另外顺便说一句,如果您希望输出中包含花括号,请将行更改print if ...print "{\n$_\n}\n" if ...


打印与您最初要求相反的内容(即打印包含以Msg该开头的行的段落包含^Msg 208.*^#.*not found)将if ...语句更改为if (/^Msg /ms && ! /^Msg 208.*^#.*not found/ms)。即(带有额外的换行和缩进以提高可读性):

sed -E -e 's/^(Msg |\])/\n\1/; s/\[/[\n/' input2.txt  |
    perl -00 -l -n -e 'print if (/^Msg /ms && 
                                 ! /^Msg 208.*^#.*not found/ms)'

答案2

在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
/^#[^ ]+ not found/ && (p2 ~ /^Msg 208,/) {
    print "{" ORS p2 ORS p1 ORS $0 ORS "}"
}
{ p2=p1; p1=$0 }

$ awk -f tst.awk file
{
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.itxxn_33', Line 40:
#old_33 not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
}
{
Msg 208, Level 16, State 1:
Server 'DEV_RP', Procedure 'dbo.yftran_33', Line 40:
#wbat not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
}

上面假设问题中的预期输出是错误的,并且包含的​​块#wbat应该包含在输出中,并且进一步假设每个输出块应该被包装在其中,{...}如果这是一个错误的假设,则更改是微不足道的。

答案3

您可以像这样一次性提取这些行sed

sed -n '1N;N;/Msg 208.*\n.*\n#[[:alnum:]_]* not found/p;D' 
  • -n抑制正常输出的选项
  • N;D始终一起处理两条线的方案;1N在文件开头添加第三行
  • 该模式Msg 208.*\n.*\n#[[:alnum:]_]* not found描述了您想要p打印的三元组

如果你想用大括号括住每场比赛,请这样做:

sed -n '1N;N;h;s/Msg 208.*\(\n\).*\n#[[:alnum:]_]* not found.*/{\1&\1}/p;g;D'

ubstitute命令s添加大括号和额外的换行符(被捕获\(\n\)并重用,\1因为\n在替换中未定义)。当然,我们需要将原来的内容保存在h旧空间中,然后用g.

相关内容