如何将行追加到上一行?

如何将行追加到上一行?

我有一个需要解析和分析的日志文件。文件包含类似如下的内容:

文件:

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收集文件中的所有行除以\n1 长行

  • 第二部分去掉换行符,如果它跟在非数字符号后面并且其之间可能有空格。

为了避免内存限制(特别是大文件),您可以使用:

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'

答案4

另一种最简单的方法(比我的其他答案)使用特登的算法:

awk 'NR>1 && /^[0-9]{8}/{printf "%s","\n"$0;next}{printf "%s",$0}END{print}' file

相关内容