在基数10中具有数字x
(0到255之间),我想在基数2中转换此数字,添加尾随零以获取12位长的二进制表示形式,生成12个不同的数字(每个数字以2为基数的最后n
个数字,n
在1到12之间),并打印这12个数字的以10为基数的表示形式。
x = 10
1010
101000000000
1
,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
因为变量x_base2_padded
包含整个序列000000000000\r1010
。在for循环中,当我提取前12个字符时,我只会得到零。
是否有办法resolve除去回车符的字符串,以便000000000000\r1010
转换为101000000000
?
我知道我可以通过如下方式在变量上添加零来找到替代方法:
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)"
尽管这些替代方法现在可以解决我的问题,让我继续工作,但并不能真正回答我的问题。
以下函数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
[C0函数还支持用参数覆盖而不是用overwrite
分隔的段:
\r
要就地转换变量,请使用子外壳:$ overwrite abcdef 0123 xy
xy23ef
使用awk,您将字段定界符设置为myvar=$(overwrite "$myvar")
,并仅遍历只打印可见部分的字段。
\r
这确实太长了,无法替换为命令。因此,最好将其包装在一个函数中,然后将要解析的行用管道传递给该函数。
要回答特定问题,如何将awk -F'\r' '{
offset = 1
for (i=NF; i>0; i--) {
if (offset <= length($i)) {
printf "%s", substr($i, offset)
offset = length($i) + 1
}
}
print ""
}'
转换为000000000000\r1010
,请参阅101000000000
。
但是,我不会首先介绍回车符并解决这样的问题:
Socowi's answer