在unix中重新格式化txt文件



我有一个文件,其中包含一个进程的名称、它死亡的次数和它死亡的原因。文件看起来像这样:

  26 posix.cc:529 ---PROCESS: cat
  18 XtWindowOfObject () from /usr/lib64/libXt.so.6 ---PROCESS: dog
  16 _XtAddCallbackOnce () from /usr/lib64/libXt.so.6 ---PROCESS: dog
  16 Matrix.cc:4399 ---PROCESS: cat
  9 vtable for CollapsibleEvent () from /srg/release/lib.so ---PROCESS: bird
  1 raise () from /lib64/libc.so.6 ---PROCESS: dog
  1 raise () from /lib64/libc.so.6 ---PROCESS: cat
  1 ?? () ---PROCESS: cat

我想使用一个命令重新排列它,使它有以下3列,像这样:

  CAT PROCESS CORES:
  cat     26     posix.cc:529
  cat     16     Matrix.cc:4399
  cat     1      raise () from /lib64/libc.so.6
  cat     1      ?? ()
  DOG PROCESS CORES:
  dog     18     XtWindowOfObject () from /usr/lib64/libXt.so.6
  dog     16     _XtAddCallback () from /usr/lib64/libXt.so.6
  dog     1      raise () from /lib64/libc.so.6
 BIRD PROCESS CORES: 
  bird    9     vtable for CollapsibleEvent () from /srg/release/lib.so

进程名总是随着每天生成的文件而变化。请帮助-我一直在尝试使用awk,但我只是不知道如何正确设置分隔符。

您可以使用perl:

perl -lanE 'if(/w/){push @{$r{@F[-1]}},[$F[0],"@F[1..$#F-2]"]}}{for$k(sort keys%r){say uc($k)." PROCESS CORES:";say join"t",$k,@{$_}for@{$r{$k}}}' < input_file.txt

或可读

perl -lanE '
if( /w/ ) { #if the line contains any word character
        push @{$r{@F[-1]}}, [ $F[0], "@F[1 .. $#F-2]" ] #store by last word
}
}{ #eskimo
for $k (sort keys %r) { #for each type
        say uc($k)." PROCESS CORES:";
        say join "t", $k, @{$_} for @{$r{$k}} #print lines
}
' < input_file.txt

生产:

BIRD PROCESS CORES:
bird    9       vtable for CollapsibleEvent () from /srg/release/lib.so
CAT PROCESS CORES:
cat     26      posix.cc:529
cat     16      Matrix.cc:4399
cat     1       raise () from /lib64/libc.so.6
cat     1       ?? ()
DOG PROCESS CORES:
dog     18      XtWindowOfObject () from /usr/lib64/libXt.so.6
dog     16      _XtAddCallbackOnce () from /usr/lib64/libXt.so.6
dog     1       raise () from /lib64/libc.so.6

您可以尝试以下awk命令:

awk '
/./{ process = $NF
     split($0,info,/---PROCESS:/)
     accumulate[process] = accumulate[process] process " " info[1] "n"
}
END {
  n = asorti(accumulate, sorted)
  for(i = 1;i<=n;i++){
    process = sorted[i]
    caps = toupper(process)
    printf "n%s PROCESS CORES:n%sn",caps, accumulate[process]
  }
}'

最新更新