问题
有没有办法将回车转换为字符串中的实际覆盖,以便 000000000000\r1010
转换为 101000000000
?
语境
1. 初始目标:
有号码x
(在 0 和 255 之间)以 10 为基数,我想以 2 为基数转换这个数字,添加尾随零以获得 12 位长的二进制表示,生成 12 个不同的数字(每个数字由最后的 n
数字组成)基数为 2,n
介于 1 和 12 之间)并打印这 12 个数字的基数 10 表示。
2. 示例:
x = 10
1010
101000000000
1
, 10
, 101
, 1010
, 10100
, 101000
, ... 1
, 2
, 5
, 10
, 20
, 40
, ... 3.我做了什么(它不起作用):
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
4. 为什么它不起作用
因为变量
x_base2_padded
包含整个序列 000000000000\r1010
.这可以使用 hexdump
确认例如。在 for 循环中,当我提取前 12 个字符时,我只得到零。5. 替代品
我知道我可以通过在变量中逐字添加零来找到替代方法,如下所示:
x_base2=1010
x_base2_padded="$(printf '%s%0.*d' "${x_base2}" $((12-${#x_base2})) 0)"
或者使用
printf
用零填充和 rev
x_base2=1010
x_base2_padded="$(printf '%012s' "$(printf "${x_base2}" | rev)" | rev)"
虽然这些替代方案现在解决了我的问题并让我继续我的工作,但它并没有真正回答我的问题。
相关问题
在不同的上下文中可能会观察到相同的问题。例如,如果尝试连接多个包含回车的字符串。结果可能很难预测。
str=$'bar\rfoo'
echo "${str}"
echo "${str}${str}"
echo "${str}${str}${str}"
echo "${str}${str}${str}${str}"
echo "${str}${str}${str}${str}${str}"
第一
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"
}
例子
$ overwrite $'abcdef\r0123\rxy'
xy23ef
请注意,打印的字符串实际上是
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
函数
overwrite
还支持通过参数覆盖而不是 \r
- 分隔段:$ overwrite abcdef 0123 xy
xy23ef
要就地转换变量,请使用子shell:
myvar=$(overwrite "$myvar")
关于string - 将回车 (\r) 转换为实际覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62217137/