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

问题描述 投票:2回答:4

问题

是否有一种方法可以将回车符转换为字符串中的实际覆盖值,以便将000000000000\r1010转换为101000000000

上下文

1。最初目标:

在基数10中具有数字x(0到255之间),我想在基数2中转换此数字,添加尾随零以获取12位长的二进制表示形式,生成12个不同的数字(每个数字以2为基数的最后n个数字,n在1到12之间),并打印这12个数字的以10为基数的表示形式。

2。示例:

  1. 带有x = 10
  2. 基数2为1010
  3. 带有尾随零101000000000
  4. 提取12个“前导”数字:110101101010100101000,...
  5. 转换为基数10:125102040,...

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

或通过使用printfrev用零填充

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

string bash formatting carriage-return
4个回答
3
投票

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


2
投票

使用awk,您将字段定界符设置为myvar=$(overwrite "$myvar"),并仅遍历只打印可见部分的字段。

\r

这确实太长了,无法替换为命令。因此,最好将其包装在一个函数中,然后将要解析的行用管道传递给该函数。


1
投票

要回答特定问题,如何将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

0
投票

除非我丢失任何东西,这仅是对#!/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
© www.soinside.com 2019 - 2024. All rights reserved.