将回车 return (\r) 转换为实际覆盖
Convert carriage return (\r) to actual overwrite
问题
有没有办法将回车 returns 转换为字符串中的实际覆盖,以便 000000000000\r1010
转换为 101000000000
?
上下文
1。初始objective:
有一个以 10 为底的数字 x
(介于 0 和 255 之间),我想将这个数字转换为以 2 为底的数字,添加尾随零以获得 12 位长二进制表示,生成 12 个不同的数字(它们中的每一个都由基数 2 中的最后 n
数字组成,n
在 1 和 12 之间)并打印这 12 个数字的基数 10 表示。
2。示例:
- 与
x = 10
- 基数 2 是
1010
- 尾随零
101000000000
- 提取12个"leading"号码:
1
、10
、101
、1010
、10100
、101000
, ...
- 转换为 10 进制:
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)"
虽然这些替代方案现在解决了我的问题并让我继续我的工作,但它并没有真正回答我的问题。
相关问题
在不同的上下文中可能会观察到相同的问题。例如,如果一个人试图连接多个包含回车 returns 的字符串。结果可能很难预测。
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
.
回答具体问题,如何将000000000000\r1010
转换为101000000000
,参考。
但是,我不会首先引入马车return,而是这样解决问题:
#!/usr/bin/env bash
x=
# 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
以下函数 overwrite
转换其参数,以便在每次回车后 return \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")
使用 awk,您可以将字段分隔符设置为 \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 ""
}'
这确实太长了,无法放入命令替换。所以你最好将它包装在一个函数中,并将要解析的行传递给它。
问题
有没有办法将回车 returns 转换为字符串中的实际覆盖,以便 000000000000\r1010
转换为 101000000000
?
上下文
1。初始objective:
有一个以 10 为底的数字 x
(介于 0 和 255 之间),我想将这个数字转换为以 2 为底的数字,添加尾随零以获得 12 位长二进制表示,生成 12 个不同的数字(它们中的每一个都由基数 2 中的最后 n
数字组成,n
在 1 和 12 之间)并打印这 12 个数字的基数 10 表示。
2。示例:
- 与
x = 10
- 基数 2 是
1010
- 尾随零
101000000000
- 提取12个"leading"号码:
1
、10
、101
、1010
、10100
、101000
, ... - 转换为 10 进制:
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)"
虽然这些替代方案现在解决了我的问题并让我继续我的工作,但它并没有真正回答我的问题。
相关问题
在不同的上下文中可能会观察到相同的问题。例如,如果一个人试图连接多个包含回车 returns 的字符串。结果可能很难预测。
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
.
回答具体问题,如何将000000000000\r1010
转换为101000000000
,参考
但是,我不会首先引入马车return,而是这样解决问题:
#!/usr/bin/env bash
x=
# 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
以下函数 overwrite
转换其参数,以便在每次回车后 return \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")
使用 awk,您可以将字段分隔符设置为 \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 ""
}'
这确实太长了,无法放入命令替换。所以你最好将它包装在一个函数中,并将要解析的行传递给它。