使用 printf 格式化输出:截断或填充
Formatting output with printf: truncating or padding
我想产生以下输出:
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schim... 250 40
如您所见,少于 14 个字符的名称会用空格填充。长度超过 15 个字符的名称将被截断:'Yutte Schimmelpenninck' 截断为 'Yutte Schim...'。
这是我试图实现的(变量 $name
、$height
和 $weight
是从文件中提取的,循环运行 printf
每个文件数据上的命令):
printf '%-14s -%3s -%3s\n' "$name" "$height" "$weight"
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schimmelpenninck 250 40
一个 printf
一行是所需的解决方案。
什么代码会产生第一个输出块?
在您的 printf
命令之前,您想检查一个名称是否超过 14 个字符,如果是,截断它并将最后三个字符替换为点。此命令执行此操作:
(( ${#name} > 14 )) && name="${name:0:11}..."
它将 name
替换为其前 11 个字符并附加 ...
。
您还必须修复 printf
格式字符串:而不是
'%-14s -%3s -%3s\n'
必须
'%-14s %-3s -%-3s\n'
或者您得到的结果如
Avril Stewart - 99 - 54
不过,也许这只是一个拼写错误,因为您的示例输出没有连字符。
总而言之:
$ name='Avril Stewart'; weight=99; height=54
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Avril Stewart 99 54
$ name='Sally Kinghorn'; weight=170; height=60
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Sally Kinghorn 170 60
$ name='Yutte Schimmelpeninck'; weight=250; height=40
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Yutte Schim... 250 40
所以如果你从一个文件中读取这个,例如逗号分隔,你最终会得到这样一个循环:
while IFS=, read -r name weight height; do
(( ${#name} > 14 )) && name="${name:0:11}..."
printf '%-14s %-3s %-3s\n' "$name" $weight $height
done < inputFile
导致
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
我认为单行是不可能的。我尝试了三元运算符并尝试了类似
printf '%s\n' $(( ${#name} > 14 ? "${name:0:11}..." : "$name" ))
但这里的问题是它只适用于整数,而字符串在算术上下文中扩展为零。
更惯用的 awk
版本将是
$ awk '{v= FS }
length(v)>14{v=substr(v,1,11)"..."}
{printf "%-15s %-3d %-3d\n",v,,}' file
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
如果您删除 %-3d 中的 -
符号,数字将照常右对齐,但这是您要求的格式。
这是部分答案 -- 忽略最后的“...”:
awk '{printf "%-14.14s %-3d %-3d\n", FS ,,}'
其中 %-14.14s
对名称进行填充 + 截断格式化
我想产生以下输出:
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schim... 250 40
如您所见,少于 14 个字符的名称会用空格填充。长度超过 15 个字符的名称将被截断:'Yutte Schimmelpenninck' 截断为 'Yutte Schim...'。
这是我试图实现的(变量 $name
、$height
和 $weight
是从文件中提取的,循环运行 printf
每个文件数据上的命令):
printf '%-14s -%3s -%3s\n' "$name" "$height" "$weight"
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schimmelpenninck 250 40
一个 printf
一行是所需的解决方案。
什么代码会产生第一个输出块?
在您的 printf
命令之前,您想检查一个名称是否超过 14 个字符,如果是,截断它并将最后三个字符替换为点。此命令执行此操作:
(( ${#name} > 14 )) && name="${name:0:11}..."
它将 name
替换为其前 11 个字符并附加 ...
。
您还必须修复 printf
格式字符串:而不是
'%-14s -%3s -%3s\n'
必须
'%-14s %-3s -%-3s\n'
或者您得到的结果如
Avril Stewart - 99 - 54
不过,也许这只是一个拼写错误,因为您的示例输出没有连字符。
总而言之:
$ name='Avril Stewart'; weight=99; height=54
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Avril Stewart 99 54
$ name='Sally Kinghorn'; weight=170; height=60
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Sally Kinghorn 170 60
$ name='Yutte Schimmelpeninck'; weight=250; height=40
$ (( ${#name} > 14 )) && name="${name:0:11}..."
$ printf '%-14s %-3s %-3s\n' "$name" $weight $height
Yutte Schim... 250 40
所以如果你从一个文件中读取这个,例如逗号分隔,你最终会得到这样一个循环:
while IFS=, read -r name weight height; do
(( ${#name} > 14 )) && name="${name:0:11}..."
printf '%-14s %-3s %-3s\n' "$name" $weight $height
done < inputFile
导致
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
我认为单行是不可能的。我尝试了三元运算符并尝试了类似
printf '%s\n' $(( ${#name} > 14 ? "${name:0:11}..." : "$name" ))
但这里的问题是它只适用于整数,而字符串在算术上下文中扩展为零。
更惯用的 awk
版本将是
$ awk '{v= FS }
length(v)>14{v=substr(v,1,11)"..."}
{printf "%-15s %-3d %-3d\n",v,,}' file
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
如果您删除 %-3d 中的 -
符号,数字将照常右对齐,但这是您要求的格式。
这是部分答案 -- 忽略最后的“...”:
awk '{printf "%-14.14s %-3d %-3d\n", FS ,,}'
其中 %-14.14s
对名称进行填充 + 截断格式化