Sla*_*agt 5 string bash formatting carriage-return
有没有办法将回车转换为字符串中的实际覆盖,以便000000000000\r1010转换为101000000000?
有一个x以 10 为基数的数字(0 到 255 之间),我想将这个数字转换为以 2 为基数的数字,添加尾随零以获得 12 位长的二进制表示,生成 12 个不同的数字(每个n数字由基数为 2,n介于 1 和 12 之间)并打印这 12 个数字的基数 10 表示。
x = 1010101010000000001, 10, 101, 1010, 10100, 101000, ...1, 2, 5, 10, 20, 40, ...x=10
x_base2="$(echo "obase=2;ibase=10;${x}" | bc)"
x_base2_padded="$(printf '%012d\r%s' 0 "${x_base2}")"
for i in {1..12}
do
t=$(echo ${x_base2_padded:0:${i}})
echo "obase=10;ibase=2;${t}" | bc
done
Run Code Online (Sandbox Code Playgroud)
因为变量x_base2_padded包含整个序列000000000000\r1010。这可以通过hexdump例如使用来确认。在 for 循环中,当我提取前 12 个字符时,我只得到零。
我知道我可以通过在变量中逐字添加零来找到替代方法,如下所示:
x_base2=1010
x_base2_padded="$(printf '%s%0.*d' "${x_base2}" $((12-${#x_base2})) 0)"
Run Code Online (Sandbox Code Playgroud)
或者使用printf和填充零rev
x_base2=1010
x_base2_padded="$(printf '%012s' "$(printf "${x_base2}" | rev)" | rev)"
Run Code Online (Sandbox Code Playgroud)
虽然这些替代方案现在解决了我的问题并让我继续我的工作,但它并没有真正回答我的问题。
在不同的上下文中可能会观察到相同的问题。例如,如果尝试连接多个包含回车的字符串。结果可能很难预测。
str=$'bar\rfoo'
echo "${str}"
echo "${str}${str}"
echo "${str}${str}${str}"
echo "${str}${str}${str}${str}"
echo "${str}${str}${str}${str}${str}"
Run Code Online (Sandbox Code Playgroud)
第一个echo将输出foo. 尽管您可能期望另一个echo输出foofoofoo...,但它们都输出foobar。
以下函数overwrite转换其参数,以便在每次回车后\r实际上覆盖字符串的开头:
overwrite() {
local segment result=
while IFS= read -rd $'\r' segment; do
result="$segment${result:${#segment}}"
done < <(printf '%s\r' "$@")
printf %s "$result"
}
Run Code Online (Sandbox Code Playgroud)
$ overwrite $'abcdef\r0123\rxy'
xy23ef
Run Code Online (Sandbox Code Playgroud)
请注意,打印的字符串实际上是xy23ef,不像echo $'abcdef\r0123\rxy'它似乎只打印相同的字符串,但仍然打印\r然后由您的终端解释,以便结果看起来相同。您可以通过以下方式确认hexdump:
$ echo $'abcdef\r0123\rxy' | hexdump -c
0000000 a b c d e f \r 0 1 2 3 \r x y \n
000000f
$ overwrite $'abcdef\r0123\rxy' | hexdump -c
0000000 x y 2 3 e f
0000006
Run Code Online (Sandbox Code Playgroud)
该函数overwrite还支持通过参数而不是\r-delimited 段覆盖:
$ overwrite abcdef 0123 xy
xy23ef
Run Code Online (Sandbox Code Playgroud)
要就地转换变量,请使用子shell: myvar=$(overwrite "$myvar")