I would like to produce the following output:
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schim... 250 40
As you can see, names shorter than 14 characters are padded with spaces. Names longer than 15 characters are truncated: 'Yutte Schimmelpenninck' truncates to 'Yutte Schim...'.
Here is what I have tried to achieve this (the variables $name
, $height
, and $weight
are extracted from files, and a loop runs the printf
command on each file data):
printf '%-14s -%3s -%3s\n' "$name" "$height" "$weight"
> Avril Stewart 99 54
> Sally Kinghorn 170 60
> John Young 195 120
> Yutte Schimmelpenninck 250 40
A printf
one-liner is the desired solution.
What code will produce the first block of output?
Before your printf
command, you want to check if a name is longer than 14 characters, and if yes, truncate it and replace the last three characters with dots. This command does that:
(( ${#name} > 14 )) && name="${name:0:11}..."
It replaces name
with its first eleven characters and appends ...
.
You also have to fix the printf
format string: instead of
'%-14s -%3s -%3s\n'
it has to be
'%-14s %-3s -%-3s\n'
or you get results such as
Avril Stewart - 99 - 54
Maybe that was just a typo, though, as your example output didn't have the hyphens.
All in all:
$ 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
So if you read this from a file, for example comma separated, you'd end up with a loop like this:
while IFS=, read -r name weight height; do
(( ${#name} > 14 )) && name="${name:0:11}..."
printf '%-14s %-3s %-3s\n' "$name" $weight $height
done < inputFile
resulting in
Avril Stewart 99 54
Sally Kinghorn 170 60
John Young 195 120
Yutte Schim... 250 40
I don't think it's possible in a one-liner. I experimented with the ternary operator and tried something like
printf '%s\n' $(( ${#name} > 14 ? "${name:0:11}..." : "$name" ))
but the problem here is that it only works for integers, and strings expand to zero in arithmetic context.
a more idiomatic awk
version will be
$ 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
if you remove the -
sign in %-3d, numbers will be right aligned as usual, however this the format you asked for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With