根据单行参数从文本文件中提取行

根据单行参数从文本文件中提取行

我对脚本编写很陌生,所以我很感谢任何帮助。我有一个文本文件,在某些情况下可能会很长,文本行的每个部分大约有 6/7 行长。它是一个日志文件,每个部分都以时间戳一词开头。每段行之间有一个空行。每个剖面行都以分号结束。

timestamp=201706291035.....;
  line 2;
  line 3;
  line 4;
  line 5;
  line 6;
  line 7;

timestamp=201706291038.....;
  line 2;
  line 3;
  line 4;
  line 5;
  line 6;

我需要能够在一行中将每个部分提取到另一个文本文件中。最好没有最后一个分号。

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

这些信息足以找到解决方案吗?

这是一个直接的例子:

时间戳=2017-06-28-01.01.35.080576;
事件状态=0;
用户ID=用户1;
authid=用户1;
应用程序ID = 10.10.10.10.11111.12345678901;
应用程序名称=GUI;

时间戳=2017-06-28-01.01.36.096486;
事件状态=0;
用户ID=用户1;
authid=用户1;
应用程序ID = 10.10.10.10.11111.12345678901;
应用程序名称=GUI;
语句文本=从数据库中选择 table.field, table.field, table.field where table.field = value

运行脚本 @steeldriver 后,源文件和目标文件看起来相同。

答案1

这可以使用惯用的 awk 来完成,如下所示:

awk '$1=$1' RS= OFS= infile

输出:

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

解释

这里装了很多东西。基本上有三个步骤:

  1. 首先,根据记录分隔符 ( RS) 将输入拆分为记录。
  2. 每条记录根据字段分隔符 ( FS) 拆分为多个字段。
  3. 打印时,输出字段分隔符 ( OFS) 用作字段分隔符。

当 awk 解析其输入时,有几个隐式规则在起作用。读取数据时,一次一条记录,记录之间用 分隔RS(默认为\n)。当RS为空时,如上例所示,空行分隔记录。因此,每个部分都作为记录读入。

为了强制awk替换FS为,OFS我们将第一个字段设置$1为其自身。

编辑

正如所指出的钢铁起子,OP想要删除尾随的分号。无耻抄袭:

awk '{ sub(/;$/,"",$NF); $1=$1 } 1' RS= OFS= infile

答案2

这可以通过以下方式完成:

perl -lF';\n?' -00ne '$,=";"; print @F' yourfile

输出

timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

在职的

  1. Perl 选项

    a) -l=> ORS="\n" + RS = "\n"

    b) -F';\n?'=> 将使 FS 成为分号,后跟可选的换行符。

    c) -00=> 将使 RS= 从而启用段落模式。

    d) -n=> 将启用隐式文件读入+显式打印。

  2. Main:$,=;会给OFS加上分号,是根据@F当前记录划分出来的字段。$_FS

答案3

如果时间戳之前有空行,您可以使用简单的

perl -pe 'chomp unless /^$/'

如果换行符不存在,则需要记住上一行。

perl -pe 'chomp; print "\n" if $. > 1 && /^timestamp=/; print }{ print "\n"'

答案4

只是因为,这是一种方法sed

以这句话为我们的起点Peter Krumins 的 Sed 行话解释,第一部分:文件间距、编号以及文本转换和替换

  1. 如果一行以反斜杠“\”结尾,则将其追加到下一行。

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    

第一个表达式 ':a' 创建一个命名标签“a”。第二个表达式查看当前行是否以反斜杠“\”结尾。如果存在,它将使用“N”命令将其与其后面的行连接起来。然后使用“s/\\n//”命令删除连接行之间的斜杠和换行符。如果替换成功,我们分支到表达式的开头并再次执行相同的操作,希望我们可能有另一个反斜杠。如果替换不成功,则该行不会以反斜杠结尾,我们会将其打印出来。

替换\\;并调整替换以保留;但删除前导空格,我们得到

$ sed -e :a -e '/;$/N; s/\n *//; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;

timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

关闭!现在我们想要挤出空白行 - 我们可以通过测试模式是否可以做到这一点结束在换行符中(即附加行为空),如果是则打印取决于换行符然后丢弃模式:

$ sed -e :a -e '/;$/N; /\n$/{P;d;}; s/\n *//; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7;
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6;

现在我们只需要修剪掉尾随的;.一种方法是在将行附加到模式空间时删除每个行;,然后在丢弃换行符时重新插入它:

$ sed -e :a -e '/;$/{s///;N;}; /\n$/{P;d;}; s/\n */;/; ta' infile
timestamp=201706291035.....;line 2;line 3;line 4;line 5;line 6;line 7
timestamp=201706291038.....;line 2;line 3;line 4;line 5;line 6

最后一个;不会被重新插入,因为我们已经用 吃掉了换行符,所以{P;d;}替换s//\n /;/不会被应用。

相关内容