Reputation: 43
Hello I need parse a log. I have a problem when log has more than one line (in case of error) For example: If no errors
Last error code [0], message [No errors encountered.]
If conversion error
Last error code [8425], message [ERROR: Writer execution failed.
Database error: [0] [
FnName: Execute -- [DataDirect][ODBC SQL Server Wire Protocol driver][Microsoft SQL Server]Conversion failed when converting the varchar value 'amica' to data type int., SQLSTATE [22005]
FnName: Execute -- [DataDirect][ODBC lib] Function sequence error, SQLSTATE [S1010]]]
I need to get log between [ ]
Base on first example it should be:
No errors encountered.
base on second example it should be:
ERROR: Writer execution failed. Database error: [0] [FnName: Execute -- [DataDirect][ODBC SQL Server Wire Protocol driver][Microsoft SQL Server]Conversion failed when converting the varchar value 'amica' to data type int., SQLSTATE [22005]FnName: Execute -- [DataDirect][ODBC lib] Function sequence error, SQLSTATE [S1010]]
I'm writing my script in awk. Is it possible to do this using regular expressions? I'm not familiar with regular expressions, but I tried something like this
(?<=, message \[).+\n
but it doesn't work with log which has many lines, and I don't know how to cut last one char "]"
Upvotes: 0
Views: 87
Reputation: 2325
Here, an awk script:
{
# Count open and close brackets
line = $0
nb_open = gsub(/\[/, "x", line)
line = $0
nb_close = gsub(/\]/, "x", line)
}
inError == 0 && nb_open == nb_close {
# not in a block and brackets are balanced
errorLine = ""
print "No errors encountered."
next
}
inError == 0 && nb_open != nb_close {
# not in a block and brackets are unbalanced
inError = 1
errorLine = $0
# remove error header
gsub(/^.*, message \[ERROR: /, "ERROR:", errorLine)
# initialize total counters
nb_open_tot = nb_open
nb_close_tot = nb_close
next
}
{
# in a block, add brackets to the total counters
nb_open_tot += nb_open
nb_close_tot += nb_close
# add the current line to the future error line
errorLine = errorLine " " $0
}
inError == 1 && nb_open_tot != nb_close_tot {
# continue (current line already added)
next
}
inError == 1 && nb_open_tot == nb_close_tot {
# remove close bracket
gsub(/\]$/, "", errorLine)
# print error line
print errorLine
# reset variables
errorLine = ""
nb_open_tot = 0
nb_close_tot = 0
inError = 0
next
}
END {
# End of block not found ?
if (errorLine) {
print errorLine
}
}
Upvotes: 0
Reputation: 204488
It's not possible with a BRE or ERE as used by the mandatory POSIX tools (e.g. sed and awk) but might be possible with a PCRE using some other tool (e.g. perl), I really have no idea about that as I've never used PCREs.
You could always brute-force it by counting [
and ]
s though, e.g. using any awk in any shell on every Unix box:
$ cat tst.awk
{ rec = (NR>1 ? rec RS : "") $0 }
END {
numChars = length(rec)
for (charNr=1; charNr<=numChars; charNr++) {
char = substr(rec,charNr,1)
if ( char == "[" ) {
if ( ++depth == 1 ) {
str = ""
}
}
str = str char
if ( char == "]" ) {
if ( --depth == 0 ) {
if ( ++numStrs % 2 == 0 ) {
gsub(/^\[|]$|\n/,"",str)
print str
}
}
}
}
}
$ awk -f tst.awk file
No errors encountered.
ERROR: Writer execution failed. Database error: [0] [FnName: Execute -- [DataDirect][ODBC SQL Server Wire Protocol driver][Microsoft SQL Server]Conversion failed when converting the varchar value 'amica' to data type int., SQLSTATE [22005]FnName: Execute -- [DataDirect][ODBC lib] Function sequence error, SQLSTATE [S1010]]
The above does have to read your whole input file into memory at once. You could alternatively keep a rolling buffer that you read input lines into and reset after every print of str - left as an exercise!
The input file used to test the above is:
$ cat file
Last error code [0], message [No errors encountered.]
Last error code [8425], message [ERROR: Writer execution failed.
Database error: [0] [
FnName: Execute -- [DataDirect][ODBC SQL Server Wire Protocol driver][Microsoft SQL Server]Conversion failed when converting the varchar value 'amica' to data type int., SQLSTATE [22005]
FnName: Execute -- [DataDirect][ODBC lib] Function sequence error, SQLSTATE [S1010]]]
Upvotes: 1