是否有一种方法可以将回车符转换为字符串中的实际覆盖值,以便将000000000000\r1010
转换为101000000000
?
在基数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
。例如,可以使用hexdump
确认。在for循环中,当我提取前12个字符时,我只会得到零。
我知道我可以通过如下方式在变量上添加零来找到替代方法:
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
[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
除非我丢失任何东西,这仅是对#!/usr/bin/env bash
x=$1
# Start with 12 zeroes
var='000000000000'
# Convert input to binary
binary=$(bc <<< "obase = 2; $x")
# Rightpad with zeroes: ${#binary} is the number of characters in $binary,
# and ${var:x} removes the first x characters from $var
var=$binary${var:${#binary}}
# Print 12 substrings, convert to decimal: ${var:0:i} extracts the first
# i characters from $var, and $((x#$var)) interprets $var in base x
for ((i = 1; i <= ${#var}; ++i)); do
echo "$((2#${var:0:i}))"
done
的一个调用
echo -e
联机帮助页
-e启用反斜杠转义的解释
echo