我有一个带有stacktraces的server.log文件,其编写方式如下:
timestamp texttexttexttext \n
at texttexttexttext\n
at texttexttexttext\n
at texttexttexttext\n
caused by texttexttexttext\n
at texttexttexttext\n
at texttexttexttext\n
at texttexttexttext\n
at texttexttexttext\n
以及这样写的警告/信息,所有信息都在一行中:
timestamp texttexttexttexttext \n
我想解析日志文件,以便唯一的换行符是时间戳之前的那一行;这样堆栈跟踪都是一行,我可以稍后循环遍历它,只需要回显一次以显示整个堆栈跟踪。基本上我希望大型堆栈跟踪看起来像这样:
timestamp texttexttexttext
at texttexttexttext
at texttexttexttext
at texttexttexttext
caused by texttexttexttext
at texttexttexttext
at texttexttexttext
at texttexttexttext
at texttexttexttext\n
我试图遍历这些行,如果它以时间戳开头,我在它之前添加换行符,如果它没有以时间戳开头,我使用sed用空格替换换行符。下面是循环:注释显示我试图将它全部放在一个字符串中以便稍后循环它,但我也尝试将它全部放在一个文件中以便稍后再进行。
for x in "$(cat tempFile.txt)"
do
if [[ ! $x =~ [0-2][0-9](:+).* ]]
then
#STRINGBUILDER+=`printf "%s" $x | sed 's/"$NL"/" "/'`
printf "%s" $x | sed 's/$'\n'/" "/' > parsed.txt
else
#STRINGBUILDER+=`printf "\n%s" $x`
printf "\n%s" $x > parsed.txt
fi
done
但是,无论我以后如何遍历文件,新行似乎仍然存在。我如何摆脱它们?
答案 0 :(得分:1)
您遇到的具体问题是循环中只有一个参数:整个文件内容。这是因为"$(cat tempFile.txt)"
被引用,因此它被完全分配给变量$x
。
这里有一些(未经测试的)代码可以使用,但我也不得不质疑正则表达式...它没有锚定,所以尾随.*
是无意义...
if read line; then
while read next_line; do
if [[ $next_line =~ [0-2][0-9]: ]]; then
echo "$line"
else
echo -n "$line "
fi
line=$next_line
done
echo "$line"
fi < tempFile.txt > parsed.txt
答案 1 :(得分:0)
如果您希望从文件构造一个字符串,并echo
使用所需的行格式构建字符串,您可以这样做:
str=""
while IFS= read -r line; do
if [[ $line =~ ^[0-2][0-9]:+ ]]; then
string+="$line"
else
string+="${line/\\n/\ }"
fi
done < file
echo -en "$string\n"
如果您知道时间戳位于该行的开头,则.*
是不必要的。您可以使用^
添加正则表达式。如果您希望访问BASH_REMATCH
内置数组变量,则只需将括号括在Bash中。
答案 2 :(得分:0)
Awk声明应该有效。
awk 'BEGIN {ORS=""};!/[1-2][1-9]/ {print} /[1-2][1-9]/{printf("\n%s",$0)}' tempFile.txt > parsed.txt;
工作原理:
BEGIN {ORS=""}
将输出记录分隔符设置为空,因此不会打印换行符。
!/[1-2][1-9]/ {print}
如果它不是时间戳行(你可以添加更多正则表达式。我不知道格式)然后打印行。
/[1-2][1-9]/{printf("\n%s",$0)}'
如果是时间戳行,则打印换行符然后行