【问题标题】:Trouble parsing custom structure with shell script utilities like sed / awk / grep使用 sed / awk / grep 等 shell 脚本实用程序无法解析自定义结构
【发布时间】:2016-03-05 18:27:45
【问题描述】:

我正在尝试使用 shell 脚本从文本文件中解析出复杂的结构列表,并在这些结构中搜索一组非常具体的值。如果匹配,那么我需要打印一个变量的值。我仅限于轻量级实用程序,例如 sed、awk 和 grep(但不是 Perl)

这是一个结构示例,然后是我要查找的内容的说明:

{
    { 1, 2, 
        { 15, 25 },
        { 15, 25 }
    },
    { 3, 4,
        { 35, 45 },
        { 35, 45 }
    },
    { 5, 6,
        { 55, 65 },
        { 55, 65 }
    }
};

在这个例子中,我将解析三个结构并搜索一个结构,它的第一个值是“3”,第二个值是任何单个数字 (0-9),并且至少有一组“结构内部列表中的 35" 和 "45"。一旦我找到一个匹配项,我就会打印第二个值的值。在这种情况下,第二个结构将匹配,我需要打印出值“4”。

我不想假设空格是如何组织的,只是遵循上面的格式。 IE。它可能都在一行上,也可能在随机位置有不同的换行符组合。

有人可以帮我想想如何解决这个问题吗?

【问题讨论】:

  • 在“轻量级”实用程序中,awk 是“最重的”,并且必须成为计算嵌套级别的主力。但是 awk 是面向行的(不是字符),因此您的第一步是编写代码,以保证每个 {} 都单独在自己的行上(可选地删除过程中的任何周围空格)。先试一试。用您发现的内容更新问题。
  • 可以有更多或更少的嵌套级别,还是总是 3 层深?从该示例输入中发布您想要的预期输出。
  • 我尝试了不同的方法来删除或简化格式,但结构本身与我要搜索的内容有关,所以我要小心不要丢失所需的信息。我需要能够将每个结构视为一个单独的项目。我需要能够根据预期值搜索前两个值,并且我需要搜索“内部列表”以查找预期的一对值。我的第一个想法是将 sed 与一个指定模式的长正则表达式一起使用,然后使用捕获组来打印我正在寻找的值。我还在努力。
  • sed 用于在单个行上进行简单替换,仅此而已。由于这不是您正在做的事情,因此 sed 将是该工作的错误工具。这对 awk 来说是 100% 的工作。如果您不了解 awk,请阅读 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书。
  • 逗号是语法的一部分吗?您的第一个块第二个条目{ 15, 25 } 缺少尾随逗号。其他人都有。

标签: regex bash awk sed


【解决方案1】:

这可能是您想要的,使用 GNU awk 进行各种扩展:

$ cat tst.awk
BEGIN { RS="[{}]"; FS="\\s*,\\s*" }
depth == 2 { split($0,outer) }
(depth == 3) && (outer[1]==3) && (outer[2]~/^[0-9]$/) &&
    ((($1==35) && ($2==45)) || (($1==45) && ($2==35))) { print outer[2] }
{ depth = depth + (RT=="{" ? 1 : -1) }

$ awk -f tst.awk file
4

【讨论】:

    【解决方案2】:

    不可靠的awk 尝试

    $  awk -F"[{,}]" '/{/ && !/}/{c=($2==3)?+$3:""} 
       c~/^[0-9]$/ && $2==35 && $3==45{print c;exit}' file
    4
    

    使用布局

    【讨论】:

    • 最初在 cmets 中回答了我自己的问题,将其移至答案。
    【解决方案3】:

    感谢大家对此的帮助。我最终只能使用 sed 和 tr 来解决它,尽管它并不漂亮。我使用 tr 将所有行连接在一起,然后使用 sed 删除外部 { };,再次使用 sed 使用反向引用沿结构边界拆分行,再次使用 sed 清理结构之间的逗号和空格,然后使用“sed -n -r "s//\1/p" 验证模式中的预期值,并仅打印匹配的变量。

    我会看看你的例子,看看我是否可以从中学习。

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 2017-09-08
      • 1970-01-01
      • 2010-12-05
      • 2015-01-12
      • 2011-07-19
      • 2018-03-31
      • 1970-01-01
      • 2010-11-29
      相关资源
      最近更新 更多