【问题标题】:Is there a linux command that can cut and pick columns that match string patterns?是否有一个 linux 命令可以剪切和选择匹配字符串模式的列?
【发布时间】:2021-10-03 20:24:44
【问题描述】:

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

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

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

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

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

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

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

我的意见是


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


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

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

【问题讨论】:

  • 您所描述的内容听起来像 Awk,但您的说明并不是很容易理解。您能否请edit 提供几行示例和预期输出?请注意包含极端情况的示例,例如在哪里不应为特定输入打印输出。
  • @demi365:您可以要求awk 仅匹配某个列,但您需要告诉它分隔列的字符。或者,您可以使用cut 先选择相应的列,然后将结果与grep 匹配,但是在这种情况下,该行的其余部分的信息就没有了。但是,在您的情况下,如果键之一或值之一也包含字段分隔符,则两种方法都将失败。
  • 您的日志是 JSON 格式吗?

标签: linux bash shell command-line log-analysis


【解决方案1】:

不确定我是否真的了解您的规范,但以下 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

【讨论】:

  • 非常感谢,这或多或少地总结了我的要求,通过稍微更改输入并从命令行添加更多参数,我能够从您的解决方案中实现我想要的
猜你喜欢
  • 1970-01-01
  • 2022-06-22
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多