0

我正在尝试编写一个脚本来从提供的 ByteString 值中计算 base32 字符串,这些 ByteString 值作为键值对获得。ByteString 使用八进制转义序列和反斜杠转义序列。

考虑这个脚本:

#! /bin/bash

LINE='  bytes: "LaPaLaPa\363\""'

echo $LINE

K="${LINE%%: *}"
V="${LINE#*: }"
V="${V#\"}"
V="${V%\"}"      
K="${K^^}"

echo "KV='${K}'='${V}'"

FOO="$(printf "%b" "${V}")"
echo "=========================================="
printf "${FOO}" | wc -c
printf "${FOO}" | od -bc -tu1 -w24
printf "${FOO}" | base32 | tr -d "="
echo "Correct or at least wanted result!"
echo "------------------------------------------"
printf '%s' "${FOO}" | wc -c
printf '%s' "${FOO}" | od -bc -tu1 -w24
printf '%s' "${FOO}" | base32 | tr -d "="
echo "------------------------------------------"
printf '%b' "${FOO}" | wc -c
printf '%b' "${FOO}" | od -bc -tu1 -w24
printf '%b' "${FOO}" | base32 | tr -d "="
echo "------------------------------------------"
printf "%s" "${FOO}" | wc -c
printf "%s" "${FOO}" | od -bc -tu1 -w24
printf "%s" "${FOO}" | base32 | tr -d "="
echo "------------------------------------------"
printf "%b" "${FOO}" | wc -c
printf "%b" "${FOO}" | od -bc -tu1 -w24
printf "%b" "${FOO}" | base32 | tr -d "="

我从中得到这个输出:

bytes: "LaPaLaPa\363\""
KV='  BYTES'='LaPaLaPa\363\"'
==========================================
10
0000000 114 141 120 141 114 141 120 141 363 042
          L   a   P   a   L   a   P   a 363   "
         76  97  80  97  76  97  80  97 243  34
0000012
JRQVAYKMMFIGD4ZC
Correct or at least wanted result!
------------------------------------------
11
0000000 114 141 120 141 114 141 120 141 363 134 042
          L   a   P   a   L   a   P   a 363   \   "
         76  97  80  97  76  97  80  97 243  92  34
0000013
JRQVAYKMMFIGD424EI
------------------------------------------
11
0000000 114 141 120 141 114 141 120 141 363 134 042
          L   a   P   a   L   a   P   a 363   \   "
         76  97  80  97  76  97  80  97 243  92  34
0000013
JRQVAYKMMFIGD424EI
------------------------------------------
11
0000000 114 141 120 141 114 141 120 141 363 134 042
          L   a   P   a   L   a   P   a 363   \   "
         76  97  80  97  76  97  80  97 243  92  34
0000013
JRQVAYKMMFIGD424EI
------------------------------------------
11
0000000 114 141 120 141 114 141 120 141 363 134 042
          L   a   P   a   L   a   P   a 363   \   "
         76  97  80  97  76  97  80  97 243  92  34
0000013
JRQVAYKMMFIGD424EI

好的,那为什么我不只使用第一个结果,如果这似乎有效呢?

好吧,一个原因是我猜printf不应该在没有FORMAT字符串的情况下使用,因为应该有一些FORMAT字符串printf似乎默认使用(?)并且确实完成了我想要的?另一个原因是我有其他 ByteStrings,只有在我没有提供任何FORMAT字符串 ( printf: ...: invalid format character) 时才会出现错误,我认为当 ByteString 中有百分比字符时会发生这种情况,但我目前不确定,我没有示例不幸的是,它重现了这一点。所以我必须提供一个 FORMAT 字符串才能安全,对吧?但是正如你所看到的,当我尝试其他一些 FORMAT 字符串时,我得到了这个示例的错误结果!?!?

因此,如果有一个FORMAT字符串适用于任何情况,那么我可以只使用这个,但到目前为止我没有找到任何默认值?

那么FORMATprintf bash 内置函数的默认值是什么?

编辑我的问题的标题是详细回答的内容,因此首先感谢您。我已经学会了仔细检查概要,所以我可以自己弄清楚。问题有点复杂,因为我将八进制转义和反斜杠转义混合在一起。但是,如果我在某处使用双引号来自动插入 ByteString,那么这将插入不正确的八进制值,因为它只会转义三个数字中的第一个。所以双引号内的两个字符或字节"\363\""会变成363"所以我会得到它的 4 个字符/字节 3,6,3 和一个双引号,而不是八进制值 363 后跟双引号的字符!所以我想我的问题(现在我对 printf 有了更多的了解,并且上游推出了非标准的 ByteStrings)现在哪个是最好的/故障安全策略?以某种方式首先转换/转换八进制转义序列是否有意义?然后让 bash (我假设是 bash 在双引号 "" 之间进行插值?)剩余反斜杠的插值转义?或者我将如何分两步做到这一点?到目前为止,我在脚本中使用 printf '%s' 或 '%b' 尝试的策略最终没有得到锻炼,我现在不知道如何使它工作。

所以总结一下,我猜这里正确的策略是通过用相应的字符替换八进制转义符来减少值,或者在第一步中可能使用标准反斜杠转义符,这样结果可以在放置时被 bash 本身进一步内插双引号之间?这是正确的吗?如果是,如何做到这一点?

EDIT2 正如 Aaron 在评论中所建议的,我试图提出一个解决方案,即使用printf FORMAT字符串%b将八进制转义序列转换为字符,然后在该步骤之后立即对结果进行转换,将所有出现的 替换\"为一个双引号"

printf '%b' "${FOO}" | sed 's|\\"|"|g' | wc -c
printf '%b' "${FOO}" | sed 's|\\"|"|g' | od -bc -tu1 -w24
printf '%b' "${FOO}" | sed 's|\\"|"|g' | base32 | tr -d "="
10
0000000 114 141 120 141 114 141 120 141 363 042
          L   a   P   a   L   a   P   a 363   "
         76  97  80  97  76  97  80  97 243  34
0000012
JRQVAYKMMFIGD4ZC

这似乎有效,因为我得到了在这种情况下正确的结果。

我希望这在每种情况下都能产生正确的结果......

4

1 回答 1

1

printf不能在没有格式字符串的情况下使用:当您使用单个参数调用它时,该参数将被解析为格式。

考虑它的概要man bash

printf [-v var] 格式 [参数]

它是可选的参数列表,而不是格式。

man bash继续说在格式字符串中找到的纯字符会按原样复制到输出流中,这就是为什么您可以随意printf 'message'使用echo 'message'.

但是,它还补充说,它将识别字符转义序列以在打印之前对其进行转换(这类似于将echo -e要执行的操作),最重要的是,%X它将被(可能已转换的)附加参数替换的“格式字符序列”(子字符串) ,或者如果没有参数可以使用,则为默认值。

这就是您不应该这样做的原因printf "$message":您$message可能包含将由printf.

如果您想按原样打印消息,您将需要使用printf '%s' "$message",其中%s是要求printf将 (text) 参数输出为文本的格式说明符(因此,输出未修改)。

于 2021-08-26T15:44:59.390 回答