Bash 添加尾随空格来调整字符串

Bash 添加尾随空格来调整字符串

我当前的代码如下所示:x=${y:0:40},它将字符串的长度限制为 40 个字符。如果字符串少于 40 个字符,是否可以用空格填充尾随位置?

所以如果我的y="very short text"

我希望我的y成为:

y="非常短的文本(+25 个尾随空格)

答案1

你应该试试printf

printf '%-40s' "$y"

答案2

如果这些字符都是单字节的,也就是说,如果您所在的语言环境的字符集是单字节的(如 iso8859-1),或者语言环境的字符集是 UTF-8 但文本仅为 ASCII,您可以这样做:

printf -v y %-40.40s "$y"

这将涵盖截断和填充。

如果没有,您可以随时添加 40 个空格并使用您的${y:0:40}方法。

printf -v pad %40s
y=$y$pad
y=${y:0:40}

zsh有专用的左右填充运算符:

y=${(r:40:)y}

(也进行截断)。zshprintf计数以字符而不是字节为单位(或者如果还使用参数扩展标志,则基于字符的显示宽度m),因此不会出现bash上面的问题。但请注意,您需要zsh5.3 或更高版本才能使用该-v选项。

也可以看看这个相关问题的答案如果您遇到的字符宽度不一样,请了解更多详细信息。

答案3

纯的bash

ten="          " 
forty="$ten$ten$ten$ten" 
y="very short text"
y="${y:0:40}${forty:0:$((40 - ${#y}))}"
echo "'${y}'"

方法是对每个字符串截断后添加0-40个空格。

输出(注意单引号位置):

'very short text                         '

答案4

通常的使用建议printf是错误的,它计算的是字节,而不是字符。即使它正确地(大多数时候)计算字符,
的使用也仅限于具有数组的 shell。${var:start:length}

更好的计数方法是基于${#var}应该计算字符。

$ for var in 1 123 ΐΐΐ ᾂᾂ "㉑㉒㉓" aáéí;
> do
>     printf '|%s%*s|\n' "$var" "$((10-${#var}))" "";
> done

|1         |
|123       |
|ΐΐΐ       |
|ᾂᾂ        |
|㉑㉒㉓       |
|aáéí      |

但修剪字符串长度的唯一可移植方法是使用 grep。

#!/bin/sh
n=${1:-10}
for str in 1 123 123456789012 ΐ ΐΐΐ ΐΐΐΐΐΐΐΐΐΐ ΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐ ᾂᾂᾂᾂᾂ "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
do
    str=$str$(printf '%*s' "$n" "")                     # pad with `n` spaces.
    var=$(echo "${str}"|grep -Eo "^.{1,$n}")            # limit length to `n`
    printf '|%s|\n' "${var}" 
done

哪个打印:

|1         |
|123       |
|1234567890|
|ΐ         |
|ΐΐΐ       |
|ΐΐΐΐΐΐΐΐΐΐ|
|ΐΐΐΐΐΐΐΐΐΐ|
|ᾂᾂᾂᾂᾂ     |
|㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚|
|aáéíóúüñm |

请注意,四舍五入的数字是双倍宽度。仍然有 10 个字符,但它们占据了两倍的宽度。请注意,可以在某些 shell 中使用var=${str:0:n}.

打印函数

printf 的实现通常仅限于计数字节(根据 POSIX 规范)。 ASCII 字符或其他每个字符一个字节的字符没有问题。但大多数其他国际人物都是这样做的:
$ printf '|%-10.9s|..\n' 1234567890 ΐ U+0390 ᾂ U+1F82 "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
|123456789 |..
|ΐ        |..
|U+0390    |..
|ᾂ       |..
|U+1F82    |..
|㉑㉒㉓ |..
|aáéíó |..

请注意,printf 应该在 10 个字符的空间中打印 9 个字符,格式如下%10.9s。它确实这样做了1234567890,它在 9 处剪切了数字,并在 10 个空格中打印出来|123456789 |..。但ΐ它在一个位置上失败,在两个位置上失败,㉑㉒㉓在三个位置上失败,最后aáéíó在四个位置上失败。

这里有两个不同的问题:

  • 第一个是每个字符使用的字节数。例如, need 3,这使得其中 3 个字符成为 9 个字节( printf 所需要的)。在这种情况下,printf 将 3 个字符计为 9 个字节。
  • 第二个是每个字符的宽度。所有这些都áéíóúüñ需要两个字节,并且都是一个位置的宽度(与空格的宽度相同)。因此,printf打印aáéíó( 中的一个字节a,其余的两个字节构成 9 个字节),仅 5 个字符,加上尾随空格,使总宽度为 6,短了 4 个空格。
  • 打印时㉑㉒㉓每个字符需要 3 个字节,但每个字符使用 2 个空格的宽度,使得字符串显示时宽度为 6 个空格。

相关内容