正则表达式从右到左提取

Regex extraction from Right to Left

提问人:Jotne 提问时间:10/8/2023 更新时间:10/21/2023 访问量:106

问:

我有一些数据,我喜欢从右到左提取数据。示例数据

1,4,34
5,15
22

预期输出:

One=34  Two=4  Three=1
One=15  Two=5
One=22

这是我的正则表达式经验所得到的。

(?:(?<three>\d+),)?(?:(?<two>\d+),)?(?<one>\d+)$

但这给出了:

One=34  Two=4  Three=1
One=15  Three=5
One=22

因此,当只有两次提取时,它会失败。有什么好主意吗? PS 我没有任何 revers 工具

正则表达式 PCRE Splunk

评论

3赞 Vivick 10/8/2023
好吧,无论你做什么,正则表达式都会被评估 LTR。
0赞 Luuk 10/8/2023
当你投反对票时有什么问题?也许你的问题“不清楚”(或者“这个问题没有显示任何研究工作;不清楚或没有用“)给点击反对票的人。
1赞 The fourth bird 10/9/2023
我认为这个问题非常清楚。

答:

1赞 Vivick 10/8/2023 #1

^((?:(?<three>\d+),)(?:(?<two>\d+),)|(?:(?<two2>\d+),)?)(?<one>\d+)$是我能想到的唯一潜在解决方案,但由于捕获组必须都具有不同的名称,因此最终会得到 2 个具有不同名称的“两个”。

评论

0赞 Jotne 10/8/2023
我会接受这一点,因为我可以使用合并将两个或两个 2 合并为两个。谢谢。不是用户为什么有些人给 -1 票一这个。我一直在寻找问题的解决方案,现在正则表达式从左到右。
3赞 The fourth bird 10/8/2023 #2

您可以将前 2 组作为一个整体设为可选组:

^(?:(?:(?<three>\d+),)?(?<two>\d+),)?(?<one>\d+)$

该模式匹配:

  • ^字符串的开头
  • (?:非捕获组
    • (?:(?<three>\d+),)?(可选)捕获组“三”中的 1+ 位数字并匹配逗号
    • (?<two>\d+),捕获组“二”中的 1+ 位数字并匹配逗号
  • )?关闭非捕获组
  • (?<one>\d+)捕获组“one”中的 1+ 位数字
  • $字符串末尾

正则表达式演示

评论

1赞 Jotne 10/9/2023
谢谢。活动更:)使用 Debuggex,您甚至可以看到它是如何工作的: debuggex.com/r/5m3CH-weKEdZZMIe
0赞 Casimir et Hippolyte 10/13/2023
也可以通过使用非贪婪量词和让回溯来完成工作来避免组的嵌套。regex101.com/r/JTiKQF/1
0赞 The fourth bird 10/13/2023
@CasimiretHippolyte 很好的例子字符串 :-)看起来很有前途,让我研究一下这颗宝石。
1赞 sln 10/9/2023 #3

可以按相反的顺序命名组。
如果您正在寻找相反顺序的匹配,这是一种直接的方法。

这是一个模板正则表达式,可以根据需要进行扩展,并将在字符串中按组升序从最后一个到第一个从左到
右 (LTR) 进行匹配。

这将删除后处理步骤。

例如,这些字符串生成以下匹配数组:

1,4,34 => [34,4,1]
5,15 => [15,5]
22 => [22]

https://regex101.com/r/uo04VM/1

^(?=(?&D_n){0,2}(\d+)$)(?=(?:(?&D_n){0,1}(\d+)(?&n_D)$)?)(?=(?:(\d+)(?&n_D){2}$)?).+$(?(DEFINE)(?<D_n>\d+[^\d\r\n]+)(?<n_D>[^\d\r\n]+\d+))

扩大

^
(?=
   (?&D_n){0,2}
   ( \d+ )                       # (1)
   $
)
(?=
   (?:
      (?&D_n){0,1}
      ( \d+ )                       # (2)
      (?&n_D) $
   )?
)
(?=
   (?:
      ( \d+ )                       # (3)
      (?&n_D){2} $
   )?
)
.+ $
(?(DEFINE)
   (?<D_n> \d+ [^\d\r\n]+ )      # (4)
   (?<n_D> [^\d\r\n]+ \d+ )      # (5)
)

评论

0赞 Jotne 10/9/2023
谢谢。我确实花了一些时间来了解它是如何工作的以及你做了什么。它有三个不同的匹配项,使用不消耗线的积极前瞻来匹配整条线。您还确实使用子模式,使您不必多次拧干相同的东西。
0赞 sln 10/13/2023
@Jotne - 匹配整行是一个占位符。这是一个视觉参考,告诉引擎停止,这条线上不允许再进行匹配。
0赞 warren 10/17/2023 #4

您想要一个以相反顺序从分隔数据中提取的字段名称变量列表吗?

您可能有多少个条目?三?五?二百七十四?

您是尝试在搜索时(即在 SPL 中您正在编写/运行)还是在 props.conf 中执行此操作?

如果您尝试在搜索时执行此操作,我根本不会尝试使用正则表达式 - 使用 split()(makemv)和 mvindex()(带有负索引)来查找您想要的项目:

...
| eval mvlist=split(delimited_field,",")
...
| eval three=mvindex(mvlist,-3)
...

评论

0赞 warren 10/17/2023
这里还有其他一些想法:community.splunk.com/t5/Splunk-Enterprise/......
0赞 Jotne 10/18/2023
那行不通。我需要第一次命中始终是最后一个数字,即使它的 or 或 .结果形式应为 22、32 或 42。那么下一个命中应该是倒数第二个命中,所以 32 和 1。(第一个数字中没有。第三次命中将仅显示 2 个。如果数字被交换了,没有问题,因为正则表达式总是从左到右命中。222/322/1/422/1/42
0赞 warren 10/19/2023
@Jotne - 将逗号上的字段拆分,然后从列表底部到顶部选择“不起作用”怎么样?
0赞 Jotne 10/21/2023 #5

为了避免从右到左使用正则表达式,我找到了一种方法来重新定义字符串。

Sed by it self 似乎限制为 9 个编号的反向引用。

echo "AbCdEfG" | sed  -r 's/(.)(.)?(.)?(.)?(.)?(.)?(.)?/\7\6\5\4\3\2\1/'
GfEdCbA

但是 sed splunk 没有这个限制(我也不需要这么多),所以

| makeresults 
| eval test="abcdefghijkl"
| rex mode=sed field=test "s/(.)(.)?(.)?(.)?(.)?(.)?(.)?(.)?(.)?(.)?(.)?(.)?/\12\11\10\9\8\7\6\5\4\3\2\1/"

给:test=lkjihgfedcba

然后从左到右使用正则表达式就可以了。