使用
xidel
我从SAMLResponse中提取//Assertion//Signature//KeyInfo//X509Certificate/text()
,这是一个X509证书作为一个长的base64字符串。
我想把这个字符串分成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
并且标记化会将整个匹配视为分隔符,分隔符不包含在输出中
echo "$SAMLRESPONSE" | base64 -D | xidel --xpath 'tokenize(//Assertion//Signature//KeyInfo//X509Certificate/text(),"(?:.{64})")' -
**** Processing: stdin:/// ****
XACcI5tcJbgsvr+ivGPos/WrhywkROwbEBh6OTNXTnaBiiIK
有没有办法在 XPath 中将字符串拆分为固定宽度的块?
如果您知道某些字符肯定不会出现在原始字符串中(例如
$
不是 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 情况下的
$
。
你的第一个想法没有错,你只是缺少 codepoints-to-string 函数:
printf %s "$SAMLRESPONSE" |
base64 -D |
xidel --xpath '
let
$cert := //Assertion//Signature//KeyInfo//X509Certificate
return
"-----BEGIN CERTIFICATE-----" || codepoints-to-string(10) ||
replace( $cert, "(.{1,64})", "$1" || codepoints-to-string(10) ) ||
"-----END CERTIFICATE-----" || codepoints-to-string(10)
'
注意: 我将正则表达式修改为
(.{1,64})
以确保“替换”字符串始终以换行符结尾
旁白: 首先,您甚至不需要使用 XPath 构建完整的输出。
{
echo '-----BEGIN CERTIFICATE-----'
printf %s "$SAMLRESPONSE" |
base64 -D |
xidel --xpath '//Assertion//Signature//KeyInfo//X509Certificate' |
fold -w 64
echo '-----END CERTIFICATE-----'
}