shell 在XPath中有没有办法将字符串分割成固定宽度的块?

ohfgkhjo  于 2023-03-09  发布在  Shell
关注(0)|答案(3)|浏览(199)

我使用xidel从SAMLResponse中提取//Assertion//Signature//KeyInfo//X509Certificate/text(),这是一个长base64字符串形式的X509证书。
我想把这个字符串分成64个字符块
我尝试使用tokenize()replace(),但我可以使它们工作,
replace()似乎不允许我在替换字符串中使用换行符\n

echo "$SAMLRESPONSE" | base64 -D | xidel --xpath 'replace(//Assertion//Signature//KeyInfo//X509Certificate/text(),"(.{64})","$1\n")' -
**** Processing: stdin:/// ****
Error:
err:FORX0004: Invalid replacement: $1\n after $1\n
Possible backtrace:
  $000000010203F668: perhaps TXQTermTryCatch + 222920 ? but unlikely
  $0000000102068BBE: perhaps Q{http://www.w3.org/2005/xpath-functions}tokenize + 166350 ? but unlikely
  $000000010203FF78: Q{http://www.w3.org/2005/xpath-functions}replace + 376
  $0000000101FF853F: TXQTermNamedFunction + 767
  $0000000101F71CE7: perhaps ? ? but unlikely

Call xidel with --trace-stack to get an actual backtrace

和tokenize将整个匹配视为分隔符,和分隔符不包括在输出中

echo "$SAMLRESPONSE" | base64 -D | xidel --xpath 'tokenize(//Assertion//Signature//KeyInfo//X509Certificate/text(),"(?:.{64})")' -
**** Processing: stdin:/// ****










XACcI5tcJbgsvr+ivGPos/WrhywkROwbEBh6OTNXTnaBiiIK

在XPath中有没有办法将字符串分割成固定宽度的块?

zvms9eto

zvms9eto1#

您的第一个想法没有错,您只需要使用代码点到字符串函数来生成换行符:

printf %s "$SAMLRESPONSE" |
base64 -D |
xidel --xpath '
    let
        $cert := //Assertion//Signature//KeyInfo//X509Certificate
    return
        "-----BEGIN CERTIFICATE-----" || codepoints-to-string(10) ||
        replace( $cert, ".{1,64}", "$0" || codepoints-to-string(10) ) ||
        "-----END CERTIFICATE-----" || codepoints-to-string(10)
' -

**注意:**我将正则表达式修改为.{1,64},以确保“replaced”字符串始终以换行符结尾
**ASIDE:**首先,您甚至不需要使用XPath构建完整的输出。

{
    echo '-----BEGIN CERTIFICATE-----'

    printf %s "$SAMLRESPONSE" |
    base64 -D |
    xidel --xpath '//Assertion//Signature//KeyInfo//X509Certificate' - |
    fold -w 64

    echo '-----END CERTIFICATE-----'
}
8fsztsew

8fsztsew2#

这可以更简单地完成,并且全部使用xidel

$ echo "$SAMLRESPONSE" | xidel -se '
  "-----BEGIN CERTIFICATE-----",
  binary-to-string(base64Binary($raw)) ! extract(
    parse-xml(.)//Assertion//Signature//KeyInfo//X509Certificate,
    ".{64}",0,"*"
  ),
  "-----END CERTIFICATE-----"
' -
  • binary-to-string()
  • extract()
o2gm4chl

o2gm4chl3#

如果你知道某个字符肯定不会出现在原始字符串中(例如$在base64或base64url中不是法律的字符),那么你可以将tokenize()replace()组合起来以获得预期的结果:

echo "$SAMLRESPONSE" | base64 -D | xidel -s --xpath 'tokenize(replace(//Assertion//Signature//KeyInfo//X509Certificate/text(),"(.{64})","$1\$"),"\$")' -| cat <(echo "-----BEGIN CERTIFICATE-----") - <(echo "-----END CERTIFICATE-----")
-----BEGIN CERTIFICATE-----
MIIC8DCCAdigAwIBAgIQGSvclGcZ8oRINlIUmlg7WzANBgkqhkiG9w0BAQsFADA0
MTIwMAYDVQQDEylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZp
Y2F0ZTAeFw0yMDA2MjIwODI4NTlaFw0yMzA2MjIwODI4NTlaMDQxMjAwBgNVBAMT
KU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQgU1NPIENlcnRpZmljYXRlMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuJds5ZQxHlRF7j10Qey++JJ84vqm
uKjSAsSqCS/JynVs5oDO7oIZvxSdbmwUWDnuBUr8bHyqd/MUYOVCjZvt0zN6+kP0
bmB7B8IP8E2amZB4Hn7bYdrPELcCPjO01gLx6ymLn/kHVUrnYjP0/+r0pos/MeM7
vY6jbCrxLt9cR6e1loC1Z04dyHw0jBHBhqKO5iXe1AVUtmt2zKt27Hck4zndQgMo
Gb8JwekQhRzL+SHLydhVZ5QctyEoT/PkAkrflmhllAGzCYBJkxqAYOk2GTWt5Gi6
/GLm6cxp2KTH7bCJWJTOmfDbJMOEAgAlcXk2KKKPRYFc96Pd5BRyIAlcpQIDAQAB
MA0GCSqGSIb3DQEBCwUAA4IBAQCBmIXI9oVTX7BSiT+hY98UTsc64G4gkuBvwKuh
xxY9oUxrRo6VM/uuArDCjtupk5Wx5YGDWTvcNXmN+h2QQnjK/83hwjsbRP4hAitF
NcvdeQNcfeXTK7Woe1Dmdms2b2U77NnEhD23mv4/IoFnfDDunkOnoottjyQqSOIz
hrO4LIQriCPsHmm/8MYGrHX1KDN69gWYAVSQi7dPcbjhdnNQN00RKQ5XrbktWcFN
GrqVOI0Usy4i7hkcitrOmZfjet5VepXzNfWA2gxgWtWJNbhSBqGT/S+OEdZfNp6s
XACcI5tcJbgsvr+ivGPos/WrhywkROwbEBh6OTNXTnaBiiIK
-----END CERTIFICATE-----

在上面的命令中,首先应用replace()来匹配64个字符的组,并用其自身加上末尾的$来替换该组,然后使用$作为tokenize的分隔符。
同样,只有当你可以访问一些你知道它不能出现在原始字符串中的字符时,比如base64中的$

相关问题