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

标签 string bash formatting carriage-return

问题

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

语境

1. 初始目标:

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

2. 示例:

  • x = 10
  • 基数 2 是 1010
  • 带有尾随零 101000000000
  • 提取 12 个“前导”数字: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)"
    

    虽然这些替代方案现在解决了我的问题并让我继续我的工作,但它并没有真正回答我的问题。

    相关问题

    在不同的上下文中可能会观察到相同的问题。例如,如果尝试连接多个包含回车的字符串。结果可能很难预测。
    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/

    相关文章:

    string - 替换字符串 n 次,从末尾开始

    python - 可变和不可变对象(immutable对象)

    bash - 使用 bash 命令行,如何将 "import package.name.*;"添加到许多 java 文件?

    lex 中的 C 关键字标识符

    python - 如何使用 Python 将代码写入 .txt 文件?

    string - 定义一个没有 hex.DecodeString 的 []byte

    regex - 如何计算字符串中某个字符的频率?

    regex - 如何使用 sed(或类似工具)删除两个 html 标签之间的所有行?

    linux - 相当于 Bash 或命令行中 perl 的 print "-"x20

    PHP 标记删除文档中的最后一个换行符