我正在做的是尝试使用diff
的--ignore-matching-lines=
来忽略包含某些模式的行。原因是我有一个BASH脚本,该脚本使用HPE的RESTFUL API检查主机上的BIOS设置。当两种正则匹配主机上的BIOS设置以及我存储在变量中的设置上时,我使用--ignore-matching-lines=
省略了BIOS设置中的模式。如果diff
发现设置与"黄金配置"不匹配,则显示终端上的差异并提示应用正确的配置。我正在使用的设置是UEFI引导订单和Intel SGX设置。
这个特定的正则问题是围绕SGX设置。HPE偶尔将时代设置为所有0的默认值。我需要确保sgxepoch值不是全部0,而是一个随机的32个字符串,如以下实例,或者我们在确保飞地分泌方面有问题。
破碎:
"SgxEpoch": "00000000000000000000000000000000"
好:
"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"
我做了很多看,发现WiktorStribiêEw在展示如何使用Posix来表明"匹配"以外的"除了"(我发现Diff不支持LookAheads(非常有帮助除了
所以我想到了以下版本,它也寻找"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版本捕获时代的非零或空白版本的示例,也没有捕获某物。
[~]$ 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])"|"")'
[~]$
我遇到的问题是我不明白上述正则是如何工作的。在我看来,这只是使用meta-character |
的一堆替代方案,我基本上是在说x数字是"除newline之外的任何字符"(通过 .{x}
(,然后再说一个 0
,然后再进行x数字x除newline以外的任何字符(通过.{x}
(。在我看来,这条正则应与以下示例相匹配,但这不...我不明白为什么。
"SgxEpoch": "00000000000000010000000000000000"
"SgxEpoch": "00000000000000000000000001000000"
"SgxEpoch": "00000100000000000000000000000000"
这里的工作与BASH脚本中的实现方式非常相似。在第一个输入fd<(curl ...(中,它以JSON格式从主机中拉出所有BIOS设置。对于第二fd<(回声...(,我以通用形式与所需的BIOS设置相呼应一个变量。然后两者都被馈送到 | python -m json.tool | perl -00pe 's:[.*?]:($x=$&)=~s/s//gs;$x:ges'
,以将两个输入标准化为diff,漂亮的打印格式,以通过n
将JSON设置分开,因此--suppress-common-lines
仅显示差异到用户,并且Perl删除了数组类型变量的 n字符跨新线作为"一个块",诸如.
之类的东西。
[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的源代码并发现它可以按线进行比较,但找不到线程。
。 note2:我注意到,当diff在一条线之前找到区分线时,在 --suppress-common-lines
Regex中会有匹配的线路时,diff不会删除匹配正则匹配的两条线,并立即将其显示为差异。在非regex匹配线之前,它发现了差异。希望我不会屠杀太糟糕。例如:
[~]$ 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"
} }
[~]$
由于数据的敏感性,我想确保我清楚地了解了这条正则是如何工作的。
,我也非常感谢您在巨大的正则线条上提供的任何语法验证,因为我不太了解它的工作原理。
此处的要求是要有人解释/验证正则条件。我认为最好是因为XY问题解释我的最终目标,但实际上我负担不起当前重新编写所有内容的时间投资。我对此持开放态度,但我有一个约会。
aaron
您的正则表达式似乎很好。也许问题是diff
的--ignore-matching-lines
选项(Shorthand -I
(,其作用与人们期望的不同。
diff -I regex
如何工作?
令a
和b
为两个文件。
如果我没有阅读文档,我希望以下两个命令等效:
diff -I regex a b
diff <(grep -v regex a) <(grep -v regex b)
这两种方式是错误的:
diff
总是考虑 Pairs 或a
和b
的行。如果两行(a
的线和b
的行(都匹配这对。即使两对匹配的两行,也可能会忽略它们。不仅两对中的两行都必须匹配,而且的所有线条都必须匹配!
第二点的示例(-y
是--side-by-side
的速记(:
diff --suppress-common-lines -yI '1|2' <(printf '1n') <(printf '2n')
diff --suppress-common-lines -yI '1|2' <(printf '1n1n') <(printf '2nXn')
1 | 2
1 | X
第一个命令按预期工作,但第二个命令没有。而不是线对(1
,2
(diff试图匹配块中的所有行((( 1
, 1
(,( 2
, X
((。那个大块的一行与整个大块的印刷不匹配。
替代diff -I
我不完全确定您的典型输入和预期输出是什么。我猜是:
您的文件
original
可能包含该行
"SgxEpoch": "00000000000000000000000000000000"
您生成的文件
generated
将0线修复到
之类的东西"SgxEpoch": "5FSQUWEED6XPC8PJ2CWZGQIS4WWKLKUI"
(您需要帮助的地方(
您想比较两个文件original
和generated
,以确保第二步中的脚本做正确的事情。为了使比较更容易,您只想看到original
的相应行是
"SgxEpoch": "00000000000000000000000000000000"
或
"SgxEpoch": ""
有一个简单的解决方案。只需抓取diff的输出:
diff --suppress-common-lines -y original generated |
grep -E '^s*"SgxEpoch"s*:s*"0*"'