我们说我有一个文件orders.txt
,其中包含以下内容:
# Description Amount Price Sum
1 Beermat 1000 0,01€ 10€
2 Glass 100 1€ 100€
3 Long description 1 10€ 10€
4 An even longer description 1 10€ 10€
5 An extra long description, for real! 1 10€ 10€
6 An extra long description, almost max. length 1 10€ 10€
7 Long description for some really fancy product and unfortunately this description is too long to fit into one line - bad luck! 1 10€ 10€
8 This line isn’t shown afterwards 1 1€ 1€
用tabstop a.k.a. \t
通常我使用一个小工具column -ts $'\t' order.txt
来格式化这些东西,这会导致类似:
# Description Amount Price Sum
1 Beermat 1000 0,01€ 10€
2 Glass 100 1€ 100€
3 Long description 1 10€ 10€
4 An even longer description 1 10€ 10€
5 An extra long description, for real! 1 10€ 10€
6 An extra long description, almost max. length 1 10€ 10€
只要一行不超过终端窗口的线宽,这样就可以正常工作。因此,对于第7行,此工具会输出column: line too long
并退出。
我正在寻找的是一种解决方案,可以为我生成如下输出:
# Description Amount Price Sum
1 Beermat 1000 0,01€ 10€
2 Glass 100 1€ 100€
3 Long description 1 10€ 10€
4 An even longer description 1 10€ 10€
5 An extra long description, for real! 1 10€ 10€
6 An extra long description, almost max. length 1 10€ 10€
7 Long description for some really fancy product 1 10€ 10€
and unfortunately this description is too long
to fit into one line - bad luck!
8 This line isn’t shown afterwards 1 1€ 1€
答案 0 :(得分:2)
处理长描述并在固定宽度后打印金额,价格和总和,同时拆分字符串以在金额,价格和汇总行之后打印剩余部分并非无足轻重。分割字符串的方法不止一种,而且更多的方法更优雅,但是一个蛮力的例子会给你一个想法。你可以按照自己的意愿整理一下。只需通过更改dwidth变量或在文件名后面提供所需宽度作为第二个参数来设置宽度。
这假设您的输入格式与您所描述的相同,字段以tabs
分隔,例如:#\tDescription\tAmount\tPrice\tSum
#!/bin/bash
test -r "$1" || {
printf "Error: insufficient input, usage ${0//*\//} <orders file>\n\n"
exit 1
}
oifs=$IFS # set IFS to only break on tab or newline
IFS=$'\t\n'
dwidth=${2:-50} # set the print width you want for description (default 50)
i=0
while read num desc amt price sum || test -n "$num"; do
# test description > width, if so print only first 50 (or on word break)
if test "${#desc}" -ge "$dwidth" ; then
for ((i=$dwidth; i>0; i--)); do
test "${desc:$i:1}" = ' ' && break
done
end=$i
printf "%2s %-*s %-8s %-8s %-8s\n" $num $dwidth "${desc:0:end}" $amt $price $sum
remain=$((${#desc}-$end)) # calculate remaining chars to print
while test "$remain" -gt 0; do # while characters remain
strt=$((end+1)) # start printing at last end
if test "$remain" -gt "$dwidth"; then # test if more than width remain
for ((i=$dwidth; i>0; i--)); do # if so, break on word
test "${desc:$((strt+i)):1}" = ' ' && break
done
end=$((strt+i)) # set end equal to start + chars in words
printf " %-*s\n" $dwidth "${desc:$strt:$i}" # print to width
else
printf " %-*s\n" $dwidth "${desc:$strt}" # print rest and break
break
fi
remain=$((${#desc}-$end)) # calculate new remaining chars
done
else # if description not > width, just print it
printf "%2s %-*s %-8s %-8s %-8s\n" $num $dwidth $desc $amt $price $sum
fi
done < "$1"
exit 0
输出:$ bash orders.sh orders.txt
# Description Amount Price Sum
1 Beermat 1000 0,01€ 10€
2 Glass 100 1€ 100€
3 Long description 1 10€ 10€
4 An even longer description 1 10€ 10€
5 An extra long description, for real! 1 10€ 10€
6 An extra long description, almost max. length 1 10€ 10€
7 Long description for some really fancy product and 1 10€ 10€
unfortunately this description is too long to fit
into one line - bad luck!
8 This line isn’t shown afterwards 1 1€ 1€
输出:$ bash orders.sh orders.txt 60
# Description Amount Price Sum
1 Beermat 1000 0,01€ 10€
2 Glass 100 1€ 100€
3 Long description 1 10€ 10€
4 An even longer description 1 10€ 10€
5 An extra long description, for real! 1 10€ 10€
6 An extra long description, almost max. length 1 10€ 10€
7 Long description for some really fancy product and 1 10€ 10€
unfortunately this description is too long to fit into one
line - bad luck!
8 This line isn't shown afterwards 1 1€ 1€