我想产生以下输出:
> 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
单线是理想的解决方案。
什么代码会产生第一个输出块?
答案 0 :(得分:7)
在printf
命令之前,您要检查名称是否超过14个字符,如果是,请截断它并用点替换最后三个字符。这个命令可以做到:
(( ${#name} > 14 )) && name="${name:0:11}..."
它用前11个字符替换name
并附加...
。
您还必须修复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" ))
但问题在于它只适用于整数,并且字符串在算术上下文中扩展为零。
答案 1 :(得分:4)
更加惯用的awk
版本
$ awk '{v=$1 FS $2}
length(v)>14{v=substr(v,1,11)"..."}
{printf "%-15s %-3d %-3d\n",v,$3,$4}' file
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
如果您删除%-3d中的-
符号,则数字将照常右对齐,但这是您要求的格式。
答案 2 :(得分:0)
这是部分答案 - 忽略最后的“......”:
awk '{printf "%-14.14s %-3d %-3d\n",$1 FS $2,$3,$4}'
其中%-14.14s
执行名称