将回车 (\r) 转换为实际覆盖

Sla*_*agt 5 string bash formatting carriage-return

问题

有没有办法将回车转换为字符串中的实际覆盖,以便000000000000\r1010转换为101000000000

语境

1. 初始目标:

有一个x以 10 为基数的数字(0 到 255 之间),我想将这个数字转换为以 2 为基数的数字,添加尾随零以获得 12 位长的二进制表示,生成 12 个不同的数字(每个n数字由基数为 2,n介于 1 和 12 之间)并打印这 12 个数字的基数 10 表示。

2. 示例:

  1. x = 10
  2. 基数 2 是 1010
  3. 带有尾随零 101000000000
  4. 提取 12 个“前导”数字:1, 10, 101, 1010, 10100, 101000, ...
  5. 转换为基数 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
Run Code Online (Sandbox Code Playgroud)

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)"
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

Soc*_*owi 6

以下函数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")