AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 729279
Accepted
404 Name Not Found
404 Name Not Found
Asked: 2022-12-22 19:29:18 +0800 CST2022-12-22 19:29:18 +0800 CST 2022-12-22 19:29:18 +0800 CST

正则表达式:仅匹配最深的列表级别

  • 772

我编制了一份游戏所需材料清单,从最上层开始一直到最原始的成分。但是,现在我正在寻找一种快速统计数字的方法。

21 reinforced alloy
    21 damascus steel
        21 steel
            21 iron dust
            21 carbon
            21 iron
        21 iron dust
        21 carbon
        21 iron
    21 hardened metal
        21 damascus steel
            21 steel
                21 iron dust
                21 carbon
                21 iron
            21 iron dust
            21 carbon
            21 iron
        21 duralmin
            21 aluminum dust
            21 copper dust
            21 aluminum
                21 aluminum dust
        21 compressed carbon
            84 carbon
        21 aluminum bronze
            21 aluminum dust
            21 bronze
                21 copper dust
                21 tin dust
                21 copper
            21 aluminum
                21 aluminum dust
    21 corinthian bronze
        21 silver dust
        21 gold dust
        21 copper dust
        21 bronze
            21 copper dust
            21 tin dust
            21 copper
    21 solder
        21 lead dust
        21 tin dust
        21 lead
            21 lead dust
    21 billon
        21 silver dust
        21 copper dust
        21 silver
            21 silver dust
    21 gold 24 carat

顶层并不重要,因为我正在寻找我需要收集的原材料。例如,21 hardened metal没关系21 damascus steel,因为我正在寻找 的总数42 damascus steel,这也不重要,因为我正在寻找42 iron dust, 42 carbon, 和42 iron(这个例子不计算列表的其余部分),原材料总数。

到目前为止,我是在一个正则表达式测试网站上这样做的,但最终我希望能够使用grep,这样我就不必打开一个网站来进行计数。我想得到类似“有 5 次碳出现,这里是匹配线”这样的东西,这样我可以更容易地计算,因为如果我知道有 5 次出现碳,其中 4 次是21 carbon1次84 carbon,我现在可以轻松计算出我总共需要21*4 + 84 = 168 carbon.

我正在尝试计算没有另一行后面有大量制表符的行数,因为大概如果它有那么它就不是原材料。

/(\t+)\d+ aluminum\n(?!\1)/g(用我想找到的任何原材料代替“铝”)

虽然这没有找到任何东西。有没有办法完全实现我试图用正则表达式实现的目标?如果是这样,如何?

感谢您的时间。


我不确定是把它放在 SO 上还是放在这个 SE 上,但鉴于我最终希望能够使用grep我认为这可能是更合适的地方。

grep
  • 3 3 个回答
  • 324 Views

3 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2022-12-23T02:54:24+08:002022-12-23T02:54:24+08:00

    如果你想使用类似 perl 的正则表达式,为什么不使用真实的东西:

    <your-file perl -l -0777 -ne '
      while (m{^(\s*+)(\d+) (.*)$(?!\n\1\s)}mg) {
        $count{$3} += $2
      }
      END {
        printf "%4d %s\n", $count{$_}, $_ for sort keys %count
      }'
    

    这使:

      84 aluminum dust
     168 carbon
      42 copper
     105 copper dust
      21 gold 24 carat
      21 gold dust
      84 iron
      84 iron dust
      42 lead dust
      63 silver dust
      63 tin dust
    

    -0777 -n意味着整个输入被吸入$_. 操作符的multiline 标志m{...}使得^and$在每一行的开头和结尾匹配,$_而不仅仅是在 的开头和结尾$_。没有s 标志,.不匹配换行符,但要注意,\s如果输入中有空行,这样做可能会抛出一些东西。

    \s*+是 的非回溯版本\s*。这里不是绝对必要的,因为后面的 ( \d+) 不能匹配空格。

    标准grep不支持类似 perl 的正则表达式,例如您正在使用的那些\d和(?!\1)perl RE 运算符,但您可以使用pcregrep它恰好也支持-o和多行模式-M:

    <your-file pcregrep -Mo '^(\s*+)\K.*$(?!\n\1\s)'
    

    您仍然需要通过管道传输到其他类似的东西perl或awk进行求和,因此与用于所有内容相比,这几乎没有优势perl。

    如果缩进可能混合了制表符和空格,您可能希望输入通过其中之一expand或unexpand首先将它们合并为空格或制表符。默认情况下,他们认为制表位与大多数终端或浏览器一样相隔 8 列(但不是 stackexchange,令人讨厌的是它们相隔 4 列),但可以看到-t更改它的选项。

    • 5
  2. JJoao
    2022-12-23T03:04:56+08:002022-12-23T03:04:56+08:00

    如果一行的级别 <= 下一个元素的级别,则该行是“原始成分”(primi)。这相当于:

    如果它的级别 <= 当前级别(或者如果它是最后一个),则上一行是 primi

    使用带有字段分隔符“\t”的 awk,级别是NF,成分是最后一个字段$NF:

    awk -F '\t' 'prevlev>=NF  {print primi}; 
                              {prevlev = NF; primi=$NF } 
                 END          {print $NF}'
    

    为了总结它们,您可以按照以下方式运行

    ... | sed 's/ /\t/' | datamash -g 2 -s sum 1
    
    • 4
  3. xiota
    2022-12-22T20:12:07+08:002022-12-22T20:12:07+08:00

    您需要使用 lookbehind 和 lookahead。您还需要一起处理整个输入,而不是逐行处理。下面的命令应该做你想做的:

    grep -Pzo '(?<=\n)(\s+)(\S[^\n]*)(?!\n\1\s)' input_file
    
    • -P启用 Perl 语法。

    • -z使用空终止符,而不是换行符。

    • -o只输出匹配项。

    • (?<=\n)在后面寻找换行符。这代替了^,它通常会匹配每行的开头。对于消极的后视,使用(?<!...)。我忽略了第一行,因为大概总会有更深的层次。如果不是这种情况,您可以在输入的开头添加一个新行,然后再将其发送到grep. 可能有更好的方法可以做到这一点,但这里有一个:

      ( echo ; cat input_file ) | grep ...
      
    • (\s+)捕获缩进级别。这在后面被称为\1。 \s匹配空白。一个潜在的问题是换行符可以被认为是缩进的一部分。例如,双换行符通常用作段落分隔符。您可以替换\s为您希望用于缩进的特定空格,[\ \t].

    • (\S[^\n]*)捕获感兴趣的文本。 \S匹配非空白。[^\n]匹配任何不是换行符的东西。

    • (?!\n\1\s)否定前瞻以确保下一行的缩进不会比当前行更深。要积极展望未来,请使用(?=...).

    • 2

相关问题

  • 来自 `service | 的意外结果 grep`

  • 读取带有单词的文本文件及其出现次数和排序的打印输出

  • 命令 ls | grep 只显示目录(当它也应该显示文件时)

  • grep 什么时候计数,什么时候不计数

  • grep --line-buffered 直到 X 行?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve