从日志文件中选择一行中的剩余文本

从日志文件中选择一行中的剩余文本

我正在使用 Bash shell 处理一些日志文件,需要将其放入 CSV 文件中。我需要的信息是流程开始日期和时间流程结束日期和时间进程 ID信息

我所做的是,grep 包括启动进程的行并将它们放入一个文件中,然后 Grep 结束进程并将它们放入第二个文件中。完成后,我获取每个文件,并使用 awk 拆分和提取所需的信息,下面是我正在使用的代码,

input=starts.txt
while IFS= read -r line
do
    procs=`echo $line | awk  '{ print $6;}' 
    date_s=`echo $line | awk '{ print $1;}'`
    time_s=`echo $line |  awk '{ print $2;}'`
    m1=`echo $line |  awk '{ print $3;}'`
    m2=`echo $line |  awk '{ print $4;}'`
    m3=`echo $line |  awk '{ print $5;}'`
    m4=`echo $line |  awk '{ print $7;}'`
    m5=`echo $line |  awk '{ print $8;}'`
    m6=`echo $line |  awk '{ print $9;}'`

 echo $procs ";" $date_s ";" $time_s ";" $m1 $m2  $m3 $m4 $m5 $m6 

one   < "$input" > result.csv

这些行具有以下格式:

02/01/2018 10:32:35      ANR4930I Reclamation process 1320 started for primary      storage pool VM_VTL_POOL automatically, threshold=75,     duration=None. (PROCESS: 1320) 

我现在有两个问题:

  1. while 循环没有结束。
  2. 提取时间/日期和进程 ID 后,我想将剩余的消息放在单独的字段中,而不是逐字逐句地进行并连接它们(m1 m2 m 3 ...)此外,如果我的代码可以进行任何改进。

答案1

最大的改进是完全避免使用 shell 循环,直接在 Awk 中处理每条记录(行)。例如:

$ awk '{
    printf("%s;%s;%s;", $6, $1, $2)
    for(i=3; i<NF;i++) {
      if(i==6) continue; 
      printf("%s ", $i)
    }
    printf("%s\n",$NF)
  }' input
1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)

答案2

我理解你的任务是“将字段 5(process number)移到前面,然后输出以 分隔的前 3 个字段;,接着是,;然后是余数。

在 Perl 中我会这样做(作为一行代码):

perl -a -n -l -e \
    'unshift @F, splice(@F, 5, 1); 
     print join(";", @F[0..2]), ";@F[3..$#F]";' \
    < input.txt > output.csv

结果:

input.txt

02/01/2018 10:32:35      ANR4930I Reclamation process 1320 started for primary      storage pool VM_VTL_POOL automatically, threshold=75,     duration=None. (PROCESS: 1320) 
02/01/2018 10:32:35      ANR4930I Reclamation process 4567 started for primary      storage pool VM_VTL_POOL automatically, threshold=75,     duration=None. (PROCESS: 1320) 

output.csv

1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
4567;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)

解释:

perl -a -n -l -e

  • 在空格处拆分每个输入行,并将结果放入预定义数组中@F
  • 处理每个输入行(但不要打印)
  • 使用输入分隔符(\n)作为输出分隔符(相当简化)
  • 对每个输入行运行以下表达式

unshift @F, splice(@F, 5, 1);

  • 从数组 (包含在空格处分割的输入文件的一行)中删除第 5个元素(count=1),并将该第 5元素添加到数组前面。@F@F

print join(";", @F[0..2]), ";@F[3..$#F]";'

  • @F打印介于;两者之间的前 2 个元素,然后
  • 后面跟着一个文字,然后 是从第 3 个元素开始到最后;数组的其余部分,以空格作为分隔符。(打印用空格分隔的项目。)@Fprint "@any_array"

如果您想要与脚本相同的代码(例如format-messages.pl),那么它看起来会略有不同,因为命令行切换到 Perl(现在缺失)隐式添加了一些现在必须明确添加的代码。(是的,有其他方式,但是...)

#!/usr/bin/env perl

use strict;
use warnings;

while(<>) {
    my @F = split;
    unshift @F, splice(@F, 5, 1); 
    print join(";", @F[0..2]), ";@F[3..$#F]\n";
}

执行 achmod +x format-messages.pl然后运行此脚本./format-messages.pl < input.txt > output.csv

相关内容