【问题标题】:RegEx: Do not match - please check my solution [duplicate]正则表达式:不匹配 - 请检查我的解决方案 [重复]
【发布时间】:2018-07-29 13:17:17
【问题描述】:

我正在做的是尝试使用diff--ignore-matching-lines= 来忽略包含某些模式的行。原因是我有一个 bash 脚本,它使用 HPE 的 RESTful API 来检查/修补主机上的 BIOS 设置。当 RegEx 与主机上的 BIOS 设置以及我存储在变量中的设置的基本模板匹配时,我使用 --ignore-matching-lines= 省略 BIOS 设置中的模式。如果diff 发现设置与“黄金配置”不匹配,则会在终端上显示差异并提示应用正确的配置。我使用 RegEx 的设置是 UEFI 引导顺序和 Intel SGX 设置。

这个特殊的 RegEx 问题与 SGX 设置有关。 HPE 有时会将 Epoch 设置为全 0 的默认值。我需要确保 SgxEpoch 值不全为 0,而是随机 32 个字符串,如下例所示,否则我们在保护 enclave 机密时遇到问题。

破碎:

"SgxEpoch": "00000000000000000000000000000000"

好的:

"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"

我看了很多遍,发现 Wiktor Stribiżew 在展示如何使用 POSIX 来“匹配所有内容”方面非常有帮助(我发现 diff 不支持前瞻,因为它是 BRE)-Regex: match everything but

所以我想出了以下 ERE 版本,它也寻找 "SgxEpoch": "",因为这就是我的比较模板的定义方式 - https://regex101.com/r/Upd1KL/1

SgxEpochRegEx='"SgxEpoch":\s*(\"([^0].{31}|.[^0].{30}|.{2}[^0].{29}|.{3}[^0].{28}|.{4}[^0].{27}|.{5}[^0].{26}|.{6}[^0].{25}|.{7}[^0].{24}|.{8}[^0].{23}|.{9}[^0].{22}|.{10}[^0].{21}|.{11}[^0].{20}|.{12}[^0].{19}|.{13}[^0].{18}|.{14}[^0].{17}|.{15}[^0].{16}|.{16}[^0].{15}|.{17}[^0].{14}|.{18}[^0].{13}|.{19}[^0].{12}|.{20}[^0].{11}|.{21}[^0].{10}|.{22}[^0].{9}|.{23}[^0].{8}|.{24}[^0].{7}|.{25}[^0].{6}|.{26}[^0].{5}|.{27}[^0].{4}|.{28}[^0].{3}|.{29}[^0].{2}|.{30}[^0].|.{31}[^0])\"|"")'

然后将其转换为 BRE,以便与 diff 一起使用:

SgxEpochRegEx='"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\)'

这是一个 BRE 版本捕获 Epoch 的非零或空白版本以及未捕获某些内容的示例。

[~]$ echo '"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"' | grep '"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\)'
"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"
[~]$ echo '"SgxEpoch": ""' | grep '"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\)'
"SgxEpoch": ""
[~]$ echo '"SgxEpoch": "00000000000000010000000000000000"' | grep '"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\)'
"SgxEpoch": "00000000000000010000000000000000"
[~]$ echo '"SgxEpoch": "00000000000000000000000000000000"' | grep '"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\)'
[~]$

我的问题是我不明白上面的 RegEx 是如何工作的。在我看来,这只是一堆使用元字符| 的替代品,我基本上是在说“除换行符之外的任何字符”的 x 个(通过.{x}),然后是0然后再x个除换行符以外的任何字符(通过.{x})。在我看来,这个 RegEx 应该与以下示例匹配,但它不...我不明白为什么。

"SgxEpoch": "00000000000000010000000000000000"
"SgxEpoch": "00000000000000000000000001000000"
"SgxEpoch": "00000100000000000000000000000000"

它的工作方式与在 bash 脚本中的实现方式非常相似。在第一个输入 fd | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges' 以按字母顺序将两个输入按字母顺序排列到差异,漂亮的打印格式以通过\n 分隔JSON 设置,因此--suppress-common-lines 仅向用户显示差异,perl 删除数组类型变量的\n 字符,因为我无法将 diff 与 . 之类的东西匹配为“一大块”换行符。

[awilk00@nvdejb-dc-2p ~]$ SgxEpochRegEx='"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\),'
[awilk00@nvdejb-dc-2p ~]$ hostsettings='{"ServicePhone":"","SgxEpoch": "00000000000000000000000000000000","SgxEpochControl":"SgxEpochNoChange","DefaultBootOrder":["PcieSlotNic","EmbeddedFlexLOM","EmbeddedStorage","PcieSlotStorage","Usb","Cd","UefiShell","Floppy"]}'
[awilk00@nvdejb-dc-2p ~]$ desiredsettings='{"ServicePhone":"","SgxEpoch": "","SgxEpochControl":"SgxEpochNoChange","DefaultBootOrder":["Floppy","Cd","Usb","EmbeddedStorage","PcieSlotStorage","EmbeddedFlexLOM","PcieSlotNic","UefiShell"]}'
[awilk00@nvdejb-dc-2p ~]$ echo "${hostsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges'
{
    "DefaultBootOrder": ["PcieSlotNic","EmbeddedFlexLOM","EmbeddedStorage","PcieSlotStorage","Usb","Cd","UefiShell","Floppy"],
    "ServicePhone": "",
    "SgxEpoch": "00000000000000000000000000000000",
    "SgxEpochControl": "SgxEpochNoChange"
}
[awilk00@nvdejb-dc-2p ~]$ echo "${desiredsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges'
{
    "DefaultBootOrder": ["Floppy","Cd","Usb","EmbeddedStorage","PcieSlotStorage","EmbeddedFlexLOM","PcieSlotNic","UefiShell"],
    "ServicePhone": "",
    "SgxEpoch": "",
    "SgxEpochControl": "SgxEpochNoChange"
}
[awilk00@nvdejb-dc-2p ~]$ diff --report-identical-files --suppress-common-lines --side-by-side --ignore-matching-lines="${SgxEpochRegEx}" <(echo "${hostsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges') <(echo "${desiredsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges')
    "DefaultBootOrder": ["PcieSlotNic","EmbeddedFlexLOM","Emb |     "DefaultBootOrder": ["Floppy","Cd","Usb","EmbeddedStorage
    "SgxEpoch": "00000000000000000000000000000000",           |     "SgxEpoch": "",
[awilk00@nvdejb-dc-2p ~]$
[awilk00@nvdejb-dc-2p ~]$
[awilk00@nvdejb-dc-2p ~]$ hostsettings='{"ServicePhone":"","SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI","SgxEpochControl":"SgxEpochNoChange","DefaultBootOrder":["PcieSlotNic","EmbeddedFlexLOM","EmbeddedStorage","PcieSlotStorage","Usb","Cd","UefiShell","Floppy"]}'
[awilk00@nvdejb-dc-2p ~]$ echo "${hostsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges'
{
    "DefaultBootOrder": ["PcieSlotNic","EmbeddedFlexLOM","EmbeddedStorage","PcieSlotStorage","Usb","Cd","UefiShell","Floppy"],
    "ServicePhone": "",
    "SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI",
    "SgxEpochControl": "SgxEpochNoChange"
}
[awilk00@nvdejb-dc-2p ~]$ echo "${desiredsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges'
{
    "DefaultBootOrder": ["Floppy","Cd","Usb","EmbeddedStorage","PcieSlotStorage","EmbeddedFlexLOM","PcieSlotNic","UefiShell"],
    "ServicePhone": "",
    "SgxEpoch": "",
    "SgxEpochControl": "SgxEpochNoChange"
}
[awilk00@nvdejb-dc-2p ~]$ diff --report-identical-files --suppress-common-lines --side-by-side --ignore-matching-lines="${SgxEpochRegEx}" <(echo "${hostsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges') <(echo "${desiredsettings}" | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&)=~s/\s//gs;$x:ges')
    "DefaultBootOrder": ["PcieSlotNic","EmbeddedFlexLOM","Emb |     "DefaultBootOrder": ["Floppy","Cd","Usb","EmbeddedStorage
[awilk00@nvdejb-dc-2p ~]$

注意:我几乎可以肯定我在堆栈溢出时发现了一个线程,其中有人查看了 diff 的源代码,发现它逐行进行比较,但找不到该线程 ATM。

注意2:我注意到,当 diff 发现在 --suppress-common-lines 正则表达式中存在匹配的行之前的差异行时,diff 不会删除与正则表达式匹配的两行并立即将它们显示为差异在前面的非正则表达式匹配行之后,它发现了一个差异。希望我没有把它杀得太糟糕。例如:

[~]$ SgxEpochRegEx='"SgxEpoch":\s*\("\([^0].\{31\}\|.[^0].\{30\}\|.\{2\}[^0].\{29\}\|.\{3\}[^0].\{28\}\|.\{4\}[^0].\{27\}\|.\{5\}[^0].\{26\}\|.\{6\}[^0].\{25\}\|.\{7\}[^0].\{24\}\|.\{8\}[^0].\{23\}\|.\{9\}[^0].\{22\}\|.\{10\}[^0].\{21\}\|.\{11\}[^0].\{20\}\|.\{12\}[^0].\{19\}\|.\{13\}[^0].\{18\}\|.\{14\}[^0].\{17\}\|.\{15\}[^0].\{16\}\|.\{16\}[^0].\{15\}\|.\{17\}[^0].\{14\}\|.\{18\}[^0].\{13\}\|.\{19\}[^0].\{12\}\|.\{20\}[^0].\{11\}\|.\{21\}[^0].\{10\}\|.\{22\}[^0].\{9\}\|.\{23\}[^0].\{8\}\|.\{24\}[^0].\{7\}\|.\{25\}[^0].\{6\}\|.\{26\}[^0].\{5\}\|.\{27\}[^0].\{4\}\|.\{28\}[^0].\{3\}\|.\{29\}[^0].\{2\}\|.\{30\}[^0].\|.\{31\}[^0]\)"\|""\),'
[~]$ desiredsettings='{"SgxEpoch": "","SgxEpochControl":"SgxEpochNoChange","DefaultBootOrder":["Floppy"]}'
[~]$ hostsettings='{"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI","SgxEpochControl":"SgxEpochNoChange","DefaultBootOrder":["PcieSlotNic"]}'
[~]$ diff --report-identical-files --side-by-side --ignore-matching-lines="${SgxEpochRegEx}" <(echo "${hostsettings}" | python -m json.tool) <(echo "${desiredsettings}" | python -m json.tool)
{                                                               {
    "DefaultBootOrder": [                                           "DefaultBootOrder": [
        "PcieSlotNic"                                         |         "Floppy"
    ],                                                              ],
    "SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI",                 "SgxEpoch": "",
    "SgxEpochControl": "SgxEpochNoChange"                           "SgxEpochControl": "SgxEpochNoChange"
}                                                               }
[~]$ diff --report-identical-files --side-by-side --ignore-matching-lines="${SgxEpochRegEx}" <(echo "${hostsettings}" | python -m json.tool | grep -v '[]],') <(echo "${desiredsettings}" | python -m json.tool | grep -v '[]],')
{                                                               {
    "DefaultBootOrder": [                                           "DefaultBootOrder": [
        "PcieSlotNic"                                         |         "Floppy"
    "SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI",           |     "SgxEpoch": "",
    "SgxEpochControl": "SgxEpochNoChange"                           "SgxEpochControl": "SgxEpochNoChange"
}                                                               }
[~]$

由于数据的敏感性,我想确保我清楚地了解这个 RegEx 的工作原理。

我也非常感谢您可以围绕庞大的正则表达式行提供的任何语法验证,因为我并不真正了解它是如何工作的。

这里的要求是让某人解释/验证正则表达式。由于 XY 问题,我认为最好解释我的最终目标,但实际上我目前无法承担重新编写所有内容的时间投资。我对此持开放态度,但我有约会。

亚伦

【问题讨论】:

  • 您的正则表达式太长,无法阅读 IMO,而且按照格式化,甚至无法在一行中查看。请修正您的格式,或者更好的是,给我们一个简单的问题。
  • 我和蒂姆在一起。您的解决方案似乎过于复杂。也许问我们如何解决实际问题而不是问如何解决您当前的方法会更快。见XY Problem
  • @TimBiegeleisen - 我不想让 RegEx 变得那么长,但基于 Wiktor Stribiżew 在stackoverflow.com/questions/1687620/regex-match-everything-but 中的解决方案,似乎没有其他方法可以让它在 POSIX 中工作.此外,当我查看问题时,我可以看到整个正则表达式?
  • @Socowi - 我要解决的问题是确定从 REST 接口返回的 SgxEpoch 值中何时全为 0。如果是这样,那么我有一些代码可以将其设置为随机字母数字值。即cat /dev/urandom | tr -dc 'A-Z0-9' | fold -w 32 | head -n 1。在我当前的解决方案中,我要求该检查的正则表达式为 BRE 格式,因此我可以使用 diff 在它不全为 0 时将其省略。我已经将diff 用于其余所有设置。
  • @R37ribution 似乎在 BRE 中“不支持甚至交替。” (link here),你有没有测试过一个基本的替代方法来检查它是否有效?就像正则表达式 ^(a|b)$ 实际上匹配 b 一样吗?此外,您当前的正则表达式允许在您的值中使用空格(“”)、制表符以及 " 之类的内容

标签: regex bash diff


【解决方案1】:

您的正则表达式看起来不错。也许问题出在diff--ignore-matching-lines 选项(简写-I),它的工作方式与人们预期的有点不同。

diff -I regex 是如何工作的?

ab 成为两个文件。

如果我没有阅读documentation,我希望以下两个命令是等效的:

diff -I regex a b
diff <(grep -v regex a) <(grep -v regex b)

这在两个方面是错误的:

  • diff 始终考虑 pairs 或来自ab 的行。如果两行(来自a 的行和来自b 的行)都与正则表达式匹配,则忽略此类对。

  • 即使这对中的两条线都匹配,它们也可能被忽略。不仅这对中的两行必须匹配,而且hunk 中的所有行都必须匹配!

第二点示例(-y--side-by-side 的简写):

diff --suppress-common-lines -yI '1\|2' <(printf '1\n') <(printf '2\n')
diff --suppress-common-lines -yI '1\|2' <(printf '1\n1\n') <(printf '2\nX\n')
1                                 | 2
1                                 | X

第一个命令按预期工作,但第二个命令没有。而不是行对 (1,2) diff 尝试匹配大块中的所有行 ((1,1),(2,X))。该大块中的一行不匹配,因此打印了整个大块。

替代diff -I

我不完全确定您的典型输入和预期输出是什么。我猜的:

  • 您的文件original 可能包含以下行
    "SgxEpoch": "00000000000000000000000000000000"

  • 您生成文件 generated,将 0 行固定为类似
    "SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"

  • (需要帮助的步骤)
    您想比较两个文件 originalgenerated 以确保您的第二步中的脚本执行了正确的操作。为了使比较更容易,您只想查看original 的对应行是
    "SgxEpoch": "00000000000000000000000000000000"
    时的差异 或
    "SgxEpoch": ""

对此有一个简单的解决方案。简单地 grep diff 的输出:

diff --suppress-common-lines -y original generated |
grep -E '^\s*"SgxEpoch"\s*:\s*"0*"'

【讨论】:

  • 非常感谢您的帮助。这个程序非常复杂,我知道你之前提到的 XY 问题。我已经 100% 实现了,我只需要验证我当前的正则表达式是否按预期工作。
  • @R37ribution 那你应该试试codereview.stackexchange。由于上述行为,您的正则表达式适用于grep,但不适用于diff -I
  • 我与您的第二个示例类似,其中 diff &lt;(printf ...) &lt;(printf ...) 但第一个输入 fd 是 &lt;(curl ...) 这会以 JSON 格式提取所有 BIOS 设置。对于第二个 fd,我以通用形式回显具有所需 BIOS 设置的变量,漂亮地打印 JSON 以通过 \n 分隔设置,因此 --suppress-common-lines 有效,然后使用 perl 删除数组类型变量的 \n 字符,因为我无法获得 @ 987654363@ 将换行符作为“一个块”与 BRE 匹配,如 @Kaddah 所说的 . 应该发生 &lt;(echo ${settings} | python -m json.tool | perl -00pe 's:\[.*?\]:($x=$&amp;)=~s/\s//gs;$x:ges')
  • 在您的示例中,ab 行的配对是我的正则表达式匹配 00000000000000000000000000000000&lt;null&gt; 的原因,因为模板设置是“”(空白)。
  • 我不相信评论“不仅这对中的两条线必须匹配,而且大块的所有线都必须匹配!”是真的...[~]$ diff --suppress-common-lines -yI '1\|2' &lt;(printf '1\n1\n') &lt;(printf '2\nX\n')1 | 21 | X[~]$ diff --suppress-common-lines -yI '1\|2' &lt;(printf '2\n1\n') &lt;(printf '2\nX\n')1 | X[~]$ 呃,结果很丑...但基本上它与您示例中“hunk”的第一行不匹配,如果他们是一样的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 2017-01-15
  • 2012-10-31
相关资源
最近更新 更多