我有一个需要解析和分析的日志文件。文件包含类似如下的内容:
文件:
20141101 server contain dump
20141101 server contain nothing
{uekdmsam ikdas
jwdjamc ksadkek} ssfjddkc * kdlsdl
sddsfd jfkdfk
20141101 server contain dump
根据上述情况,我必须检查起始行是否不包含必须附加到上一行的日期或数字。
输出文件:
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdl sddsfd jfkdfk
20141101 server contain dump
答案1
中的版本perl
,使用负向前瞻:
$ perl -0pe 's/\n(?!([0-9]{8}|$))//g' test.txt
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
-0
允许正则表达式跨域匹配整个文件,\n(?!([0-9]{8}|$))
是负向前瞻,表示换行符后面不跟有 8 位数字或行尾(使用 时,-0
将是文件的末尾)。
答案2
可能有点容易sed
sed -e ':1 ; N ; $!b1' -e 's/\n\+\( *[^0-9]\)/\1/g'
第一部分
:1;N;$!b1
收集文件中的所有行除以\n
1 长行第二部分去掉换行符,如果它跟在非数字符号后面并且其之间可能有空格。
为了避免内存限制(特别是大文件),您可以使用:
sed -e '1{h;d}' -e '1!{/^[0-9]/!{H;d};/^[0-9]/x;$G}' -e 's/\n\+\( *[^0-9]\)/\1/g'
或者忘记一个困难的sed
脚本并记住那一年从2
tr '\n2' ' \n' | sed -e '1!s/^/2/' -e 1{/^$/d} -e $a
答案3
一种方法是:
$ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
但是, .that 也删除了最后的换行符。要再次添加它,请使用:
$ { perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file; echo; } > new
解释
将-l
删除尾随换行符(并且还会在每个print
调用中添加 1,这就是我使用的原因printf
。然后,如果当前行以数字 ( /^\d+/
) 开头并且当前行号大于 1 ( $.>1
,则需要这样做以避免添加额外的换行符开头为空行),\n
在该行的开头添加一个printf
打印每行。
或者,您可以将所有\n
字符更改为\0
,然后再次将\0
数字字符串之前的字符更改为\n
:
$ tr '\n' '\0' < file | perl -pe 's/\0\d+ |$/\n$&/g' | tr -d '\0'
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
要使其仅匹配 8 个数字的字符串,请改用:
$ tr '\n' '\0' < file | perl -pe 's/\0\d{8} |$/\n$&/g' | tr -d '\0'