是否有 linux 命令可以剪切和挑选与字符串模式匹配的列?

Is there a linux command that can cut and pick columns that match string patterns?

我需要分析日志,我的最终用户必须能够以格式化的方式查看它们,如下所述,我的日志性质是 key 变量将处于不同的位置,而不是而不是基于应用程序的固定列,因为这些日志格式来自各种应用程序。

"thread":"t1","key1":"value1","key2":"value2",......"key15":"value15"

我有一种方法可以拆分和剪切它以仅分析特定的键,使用以下方法,

cat file.txt | grep 'value1' | cut -d',' -f2,7,8-

这是我能得到的命令,要求是我需要grep所有有'key1'的日志为'value1',这个值1很可能是唯一的,所以我直接使用 grep,如果需要,我可以使用 grep 来选择键和值字符串,但我面临的主要问题是,该部分是在剪切之后。我只想在这些行中选择 key2, key7, key8,但 key2, key7, key8 可能不会像按此顺序那样出现在相同的列号中,key2 甚至可能出现在第 3 列或第 4 列或 [= 之后16=]/key8,所以我想根据 key 值进行选择并得到准确的

"key2":"value2", "key7":"value7", "key8:value8"

最终用户对它们出现的顺序不是特别挑剔,他们只需要显示每行中的这些键。. 有人能帮我吗?我再次尝试使用 awk / grep 管道,但它们仍然匹配整行而不是单独在列上

我的输入是


{"@timestamp":"2021-08-05T06:38:48.084Z","level":"INFO","thread":"main","logger":"className1","message":"Message 1"} {"@timestamp":"2021-08-05T06:38:48.092Z","level":"DEBUG","thread":"main","logger":"className2","message":"Message 2"} {"@timestamp":"2021-08-05T06:38:48.092Z","level":"DEBUG","thread":"thead1","logger":"className2","message":"Message 2"}


我基本上希望我的输出更像,只找到 "thread":"main" 行并只打印匹配的每一行的键和 "logger""message" 的值,因为另一个键和值与我无关。我的文件中有超过 15 到 16 个键,并且我的键位置可以交换,例如 "message" 可能是第一个出现的,而 "logger" 可能是第二个出现在某些日志文件中的。当然,钥匙只是一个例子,我要找的真正的钥匙不只是"logger""message"

有日志分析工具,但这是一个很老的系统,日志不是实时的我正在分析和显示一些比年老得多的文件。

不确定我是否真的理解您的规范,但以下 awk 脚本可能是一个起点:

$ cat foo.awk
BEGIN {
  k["\"key1\""] = 1; k["\"key7\""] = 1; k["\"key8\""] = 1;
}
/"key1":"value1"/ {
  s = "";
  for(i = 1; i <= NF; i+=2)
    if($i in k)
      s = s (s ? "," : "") $i ":" $(i+1);
  print s;
}
$ awk -F',|:' -f foo.awk foo.txt
"key1":"value1","key7":"value7","key8":"value8"

解释:

  • awk 使用 -F',|:' 选项调用,这样每条记录中的字段分隔符就是逗号或冒号。
  • BEGIN 部分,我们声明了所选键的关联数组 (k),包括周围的双引号。
  • awk 脚本的其余部分适用于包含 "key1":"value1" 的每条记录。
    • 变量s用于准备输出字符串;它被初始化为 "".
    • 对于每个奇数字段(键),我们检查它是否在 k 中。如果是,我们连接到 s
      • 逗号如果s不为空,
      • 关键字段,
      • 一个冒号,
      • 以下偶数字段(值)。
    • 我们打印s.