我想打印 bash 函数的前两个参数,\u2263
每一侧的 unicode 字符使用两个空格分隔。问题是最终的 unicode 必须显示在第 70 列。如果 和 的字符区域$1
到达$2
第 68 列,则多余的字符将被截断。
1 2 3 V 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890
U FIRST-ARG SECOND-ARG U
U FIRST-ARG-LONGGGGGGGGGGGGGGGG SECOND-ARG U
我可以指定一个列号(例如选择34
,由字符 描述V
)作为可能的最大宽度FIRST-ARG
已开始使用cl
和的最大长度cr
。
local cl=34 cr=30
printf ' \u2263 %.${cl}s %.${cr}s \u2263\n' "$1" "$2"
答案1
请注意,在bash
,printf
中用%-63.63s
空格填充并截断为 63字节不是字符,因此不能用于格式化/对齐,除非所有字符都是单字节。 99.99% 的字符在 UTF-8 中使用多个字节进行编码。 U+2263 字符在 UTF-8 中编码为 3 个字节,在 GB18030 中编码为 4 个字节。
bash 的${var:offset:length}
,就像 ksh93 一样,它从字符级别复制它,但即便如此,也只有在所有字符都是单宽度的情况下才有效。
要正确对齐文本,可能的方法是:
- 使用考虑字符显示宽度的填充/截断运算符。
- 假设输出到达终端,请使用控制序列告诉终端在写入位置写入您想要的内容并删除您不需要的内容。
对于 1,您可以使用具有内置运算符的 shell(例如 ksh93 或 zsh)来代替 bash。
在 zsh 中:
align() printf ' \u2263 %s \u2263\n' ${(j[ ]mr[63])@}
参数r[length]
扩展标志(这里缩写为r[length][ ]
空格是默认的填充字符)r
ight 填充到给定的长度,并且使用m
,该长度以显示宽度为单位。
或者左对齐(和右垫)$1
和右对齐$2
,正如您后来澄清的那样:
align() printf ' \u2263 %s \u2263\n' "${(mr[31])1} ${(ml[31])2}"
有了ksh93
,就更简单了:
align() printf ' \u2263 %-63.63Ls \u2263\n' "$1 $2"
与%Ls
此相反,%s
它采用字符串,而不是字节,并根据其显示宽度进行填充和截断。
或者左对齐$1
和右对齐$2
:
align() printf ' \u2263 %-31.31Ls %31.31Ls \u2263\n' "$1" "$2"
请注意,如果输入包含控制字符,这些将不起作用。
对于 2,您可以:禁用自动边距,写入整个文本,移至第 68 列,然后写入" ≣"
并擦除其余部分:
am_off=$(tput rmam) am_on=$(tput smam)
col68=$(tput cr; tput cuf 68)
del_to_eol=$(tput el)
align() {
printf ' \u2263 %s\u2263%s\n' "$am_off$1 $2$col68 " "$del_to_eol$am_on"
}
答案2
让我们得到 2 个长参数:
set -- '123456789.123456789.123456789.123456789.' '987654321.987654321.987654321.987654321.'
假设我们要将 V 设置为 40,因此 field1 有 40 个字符,field2 有 68-40=28 个字符
cl=40
cr=$((68-cl))
现在我们想要打印第一个字段左对齐,第二个字段右对齐(尽管使用这些长参数是不可见的)。在 printf 格式字符串中设置字段宽度是不够的,我们还需要只获取参数的子字符串:
printf '\u2263 %-*s%*s \u2263\n' "$cl" "${1:0:cl}" "$cr" "${2:0:cr}"
≣ 123456789.123456789.123456789.123456789.987654321.987654321.98765432 ≣
我们可以看到
- “123456789.123456789.123456789.123456789.”,第一个参数的前 40 个字符,以及
- “987654321.987654321.98765432”,第二个的前 28 个字符。
答案3
啊?你需要什么?
如果问题是如何操作字符串长度,那么您可以使用此处描述的字符串函数: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
如果您需要以格式化方式打印某些内容 - 您可以printf
使用echo
.它使用与printf()
C 中完全相同的格式。https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-printf