如何将 xmlstarlet 输出与 nul 分开?
How do I separate xmlstarlet output with nul?
我正在尝试使用 nul (U+0) 来分隔 xmlstarlet 输出中的 xml 值。 xmlstarlet
忽略 -o ''
、-o $'[=15=]'
和 -o '[=16=]'
。
我知道我可以使用其他字符(例如各种字段分隔符)来分隔输出。这种方法的问题是这些字符也可以作为数据存在。我不想有任何歧义。
我想特别使用 nul,因为它是唯一不能用原始值表示的值 XML。
所以,重复我的问题:如何将 xmlstarlet 输出与 nul 分开?
更多信息
应要求提供信息的人们的要求,我提供了以下信息。虽然我很感激你愿意提供帮助,但请避免建议 XY sulutions。我只是在寻找所提出问题的答案。
我正在处理的数据如下所示:
<data>
<datapoint attribute-1="val-1" attribute-2="val-a" />
<datapoint attribute-1="val-2" attribute-2="val-b" />
<datapoint attribute-1="val-3">
<sub-datapoint />
</datapoint>
</data>
我尝试使用的方式 xmlstarlet:
mapfile -tf ARRAY < <( xmlstarlet sel -t -m /data/datapoint -o 'datapoint' -o $'[=11=]' -v ./@attribute-1 -o $'[=11=]' data.xml )
我正在寻找的输出的十六进制转储:
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 31 00 |datapoint.val-1.|
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 32 00 |datapoint.val-2.|
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 33 00 |datapoint.val-3.|
您可以使用 $''
,在大多数情况下它应该和 null 一样好:
mapfile -d $'' -t ARRAY < <( xmlstarlet sel -t -m "XPATH" -v "XPATH" -o $'' -v 'XPATH' "FILE" )
不幸的是,xmlstarlet
似乎无法在其输出中生成 nul。
然而,xmlstarlet
能够产生 U+FFFF
;在所有 XML 版本中无效的代码点。您可以使用此代码安全地分隔 XML 值,然后使用另一个程序将其替换为 nul:
xmlstarlet sel -t \
-m /data/datapoint \
-o 'datapoint' \
-o $'\uffff' \
-v ./@attribute-1 \
-o $'\uffff' data.xml \
| python3 -c 'import sys;
sys.stdout.write(sys.stdin.read().replace("\uffff", "[=10=]"))'
这是@TendersMcChiken 的答案的变体,用 perl 代替了 python:
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml \
| perl -CS -0xFFFF -l0 -pe '' \
| hexdump -e '16/1 "%-3.2x"' -e '"|" 16/1 "%_p" "|\n"'
输出与问题中显示的 hexdump 完全匹配。
旁白: 因为目标是将结果捕获到 bash 数组中,所以我尝试了这个:
mapfile -d $'\uFFFF' -t arr < <(
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml
)
但是它没有用,因为 bash 不支持多字节字符作为其 mapfile
内置的分隔符。 [discussion]
您可以做的是让 xmlstarlet 输出 0xFFFF,使用 perl(或其他东西)将 0xFFFF 转换为 NUL,最后,使用带有 NUL 定界符的 mapfile:
mapfile -d '' -t arr < <(
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml \
| perl -CS -0xFFFF -l0 -pe ''
)
我正在尝试使用 nul (U+0) 来分隔 xmlstarlet 输出中的 xml 值。 xmlstarlet
忽略 -o ''
、-o $'[=15=]'
和 -o '[=16=]'
。
我知道我可以使用其他字符(例如各种字段分隔符)来分隔输出。这种方法的问题是这些字符也可以作为数据存在。我不想有任何歧义。
我想特别使用 nul,因为它是唯一不能用原始值表示的值 XML。
所以,重复我的问题:如何将 xmlstarlet 输出与 nul 分开?
更多信息
应要求提供信息的人们的要求,我提供了以下信息。虽然我很感激你愿意提供帮助,但请避免建议 XY sulutions。我只是在寻找所提出问题的答案。
我正在处理的数据如下所示:
<data>
<datapoint attribute-1="val-1" attribute-2="val-a" />
<datapoint attribute-1="val-2" attribute-2="val-b" />
<datapoint attribute-1="val-3">
<sub-datapoint />
</datapoint>
</data>
我尝试使用的方式 xmlstarlet:
mapfile -tf ARRAY < <( xmlstarlet sel -t -m /data/datapoint -o 'datapoint' -o $'[=11=]' -v ./@attribute-1 -o $'[=11=]' data.xml )
我正在寻找的输出的十六进制转储:
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 31 00 |datapoint.val-1.|
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 32 00 |datapoint.val-2.|
64 61 74 61 70 6f 69 6e 74 00 76 61 6c 2d 33 00 |datapoint.val-3.|
您可以使用 $''
,在大多数情况下它应该和 null 一样好:
mapfile -d $'' -t ARRAY < <( xmlstarlet sel -t -m "XPATH" -v "XPATH" -o $'' -v 'XPATH' "FILE" )
不幸的是,xmlstarlet
似乎无法在其输出中生成 nul。
xmlstarlet
能够产生 U+FFFF
;在所有 XML 版本中无效的代码点。您可以使用此代码安全地分隔 XML 值,然后使用另一个程序将其替换为 nul:
xmlstarlet sel -t \
-m /data/datapoint \
-o 'datapoint' \
-o $'\uffff' \
-v ./@attribute-1 \
-o $'\uffff' data.xml \
| python3 -c 'import sys;
sys.stdout.write(sys.stdin.read().replace("\uffff", "[=10=]"))'
这是@TendersMcChiken 的答案的变体,用 perl 代替了 python:
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml \
| perl -CS -0xFFFF -l0 -pe '' \
| hexdump -e '16/1 "%-3.2x"' -e '"|" 16/1 "%_p" "|\n"'
输出与问题中显示的 hexdump 完全匹配。
旁白: 因为目标是将结果捕获到 bash 数组中,所以我尝试了这个:
mapfile -d $'\uFFFF' -t arr < <(
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml
)
但是它没有用,因为 bash 不支持多字节字符作为其 mapfile
内置的分隔符。 [discussion]
您可以做的是让 xmlstarlet 输出 0xFFFF,使用 perl(或其他东西)将 0xFFFF 转换为 NUL,最后,使用带有 NUL 定界符的 mapfile:
mapfile -d '' -t arr < <(
xmlstarlet sel -t -m /data/datapoint \
-o 'datapoint' -o $'\uFFFF' -v ./@attribute-1 -o $'\uFFFF' data.xml \
| perl -CS -0xFFFF -l0 -pe ''
)