次のテキストを含むファイルを検索し、3行目に「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
各行がまたはの各インスタンスで始まる段落に変換するために使用されます。その後、出力は短絡モード()で入力を読み取るためにパイプされ、短絡を印刷します。[
]
sed
perl
-n
-00
そして、もしこれは正規表現と一致します^Msg 208.*^#.*not found
(Perlのm
修飾子を使用して各段落を複数行の文字列として処理し、s
修飾子を使用して.
一致する改行を許可します)。
「段落」は、1つ以上の改行で区切られた1つ以上のテキスト行です。
Perlコマンドラインオプションの詳細man perlrun
とPerl正規表現の詳細についてはを参照してくださいman perlre
。 Perlスクリプトで正規表現を使用する方法のチュートリアルについては、を参照してくださいman perlretut
。
からman perlre
:
m
一致する文字列を複数行として扱います。つまり、文字列の最初の行の先頭と最後の行の終わりを一致させることから、文字列のすべての行の先頭と終わりを一致させることに^
変更します。$
s
文字列を1行として扱います。つまり、.
通常は一致しないすべての文字、改行文字まで一致するように変更します。一緒に使用すると、文字列の改行文字の後ろと前の文字をそれぞれ許可し、一致しながらすべての文字一致を
/ms
許可します。.
^
$
ちなみに、これは完全にPerlで実行できますが、sed
入力をPerlの短絡モードで簡単に処理できるものに変換する方が簡単で簡単で高速です。
また、btw、中括弧を出力に含めるには、行を次の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システムのすべてのシェルで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
常に2行を一緒に処理するシナリオは、ファイルの先頭1N
に3行目を追加します。- パターンは印刷したいトリプルを
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