我编制了一份游戏所需材料清单,从最上层开始一直到最原始的成分。但是,现在我正在寻找一种快速统计数字的方法。
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 carbon
1次84 carbon
,我现在可以轻松计算出我总共需要21*4 + 84 = 168 carbon
.
我正在尝试计算没有另一行后面有大量制表符的行数,因为大概如果它有那么它就不是原材料。
/(\t+)\d+ aluminum\n(?!\1)/g
(用我想找到的任何原材料代替“铝”)
虽然这没有找到任何东西。有没有办法完全实现我试图用正则表达式实现的目标?如果是这样,如何?
感谢您的时间。
我不确定是把它放在 SO 上还是放在这个 SE 上,但鉴于我最终希望能够使用grep
我认为这可能是更合适的地方。
如果你想使用类似 perl 的正则表达式,为什么不使用真实的东西:
这使:
-0777 -n
意味着整个输入被吸入$_
. 操作符的m
ultiline 标志m{...}
使得^
and$
在每一行的开头和结尾匹配,$_
而不仅仅是在 的开头和结尾$_
。没有s
标志,.
不匹配换行符,但要注意,\s
如果输入中有空行,这样做可能会抛出一些东西。\s*+
是 的非回溯版本\s*
。这里不是绝对必要的,因为后面的 (\d+
) 不能匹配空格。标准
grep
不支持类似 perl 的正则表达式,例如您正在使用的那些\d
和(?!\1)
perl RE 运算符,但您可以使用pcregrep
它恰好也支持-o
和多行模式-M
:您仍然需要通过管道传输到其他类似的东西
perl
或awk
进行求和,因此与用于所有内容相比,这几乎没有优势perl
。如果缩进可能混合了制表符和空格,您可能希望输入通过其中之一
expand
或unexpand
首先将它们合并为空格或制表符。默认情况下,他们认为制表位与大多数终端或浏览器一样相隔 8 列(但不是 stackexchange,令人讨厌的是它们相隔 4 列),但可以看到-t
更改它的选项。如果一行的级别 <= 下一个元素的级别,则该行是“原始成分”(primi)。这相当于:
如果它的级别 <= 当前级别(或者如果它是最后一个),则上一行是 primi
使用带有字段分隔符“\t”的 awk,级别是
NF
,成分是最后一个字段$NF
:为了总结它们,您可以按照以下方式运行
您需要使用 lookbehind 和 lookahead。您还需要一起处理整个输入,而不是逐行处理。下面的命令应该做你想做的:
-P
启用 Perl 语法。-z
使用空终止符,而不是换行符。-o
只输出匹配项。(?<=\n)
在后面寻找换行符。这代替了^
,它通常会匹配每行的开头。对于消极的后视,使用(?<!...)
。我忽略了第一行,因为大概总会有更深的层次。如果不是这种情况,您可以在输入的开头添加一个新行,然后再将其发送到grep
. 可能有更好的方法可以做到这一点,但这里有一个:(\s+)
捕获缩进级别。这在后面被称为\1
。\s
匹配空白。一个潜在的问题是换行符可以被认为是缩进的一部分。例如,双换行符通常用作段落分隔符。您可以替换\s
为您希望用于缩进的特定空格,[\ \t]
.(\S[^\n]*)
捕获感兴趣的文本。\S
匹配非空白。[^\n]
匹配任何不是换行符的东西。(?!\n\1\s)
否定前瞻以确保下一行的缩进不会比当前行更深。要积极展望未来,请使用(?=...)
.