我想在每个字段中添加尾随空格。我的文件看起来像:
输入文件:
A|B|C|D
输出文件中字段 1 的长度为:1
输出文件中字段 2 的长度为:3
输出文件中的字段 3 长度为:4
输出文件中的字段 4 长度为:6
期望的输出:
AB C D
如何在shell中实现这一点?请协助
答案1
和awk
:
awk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}' < input > output
会做正确的空间填充和截断。
根据awk
实现的不同,该长度将以字节或字符为单位(对于多字节字符会有所不同)。在任何情况下,都不基于这些字符的显示宽度(例如双宽或 0 宽度字符,或在终端上显示宽度不为 1 的 TAB)。
例子:
$ echo 'A|B|C|D' | awk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}'
AB C D
(所有这些 A
B
C
D
字素均由一个字符组成,在任何语言环境中每个字素均由一个字节组成,并且每个字素都是单宽度的)。
$ echo 'A|B|Ç|D' | gawk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}'
AB Ç D
$ echo 'A|B|Ç|D' | mawk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}'
AB Ç D
Ç
( UTF-8 中的2 字节、1 宽度字符)
$ echo $'A|B|C\u0327|D' | gawk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}'
AB Ç D
$ echo $'A|B|C\u0327|D' | mawk -F'|' '{printf "%-1.1s%-3.3s%-4.4s%-6.6s\n", $1, $2, $3, $4}'
AB Ç D
1 字节、1 宽度C
与 0 宽度、2 字节(UTF-8 格式)组合,组合变音符号以形成 1 宽度、2 个字符、3 字节Ç
字形,即预组合 U+00C7 的分解版本Ç
上一个示例中的字符。
要考虑字符的显示宽度,使用某些expand
实现(尽管不是 GNU expand
)并假设输入不包含 TAB 字符并且没有一个输入字段首先超过其分配的宽度,您可以这样做:
<input sed $'s/|/|\t/g;s/$/|\t/' | expand -t3,8,14,22 | sed 's/| //g' >output
的输出printf '%s\n' 'A|B|C|D' $'A|B|\uc7|D' $'A|B|C\u327|D'
应该给出:
AB C D
AB Ç D
AB Ç D
答案2
仅使用bash
shell 功能...
对于提供的样本数据:
$ foo="A|B|C|D"; printf "%s%s %s %s \n" $(echo -e "${foo//|/ }" )
AB C D
$ foo="A|B|C\u0327|D"; printf "%s%s %s %s \n" $(echo -e "${foo//|/ }" )
AB Ç D
对于每个问题的固定字段输出,假设没有输入字段超过其最大指定宽度:
$ foo="A|B|C|D"; printf "%-1.1s%-3.3s%-4.4s%-6.6s\n" $(echo -e "${foo//|/ }" )
AB C D
对于诸如 之类的多字节字符,您会遇到这样的问题: ( shell 内置和独立实用程序)Ç
中的宽度说明符计算的是字节,而不是多字节字符。因此,您可能会得到“意外”的输出。printf
bash
$ foo="A|B|\uc7|D"; /bin/printf "%-1.1s%-3.3s%-4.4s%-6.6s\n" $(echo -e "${foo//|/ }" )
AB Ç D
$ foo="A|B|\uc7|D"; /bin/printf "%-1.1s%-3.3s%-4.4s%-6.6s\n" $(echo -e "${foo//|/ }" ) | xxd
00000000: 4142 2020 c387 2020 4420 2020 2020 0a AB .. D .
$