使用bash工具很好地格式化字符串中的列



假设我有一个文件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(也称为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€

处理好长描述并在固定宽度后打印Amount、Price和Sum,同时拆分字符串以在Amount、Price和Sum行后打印剩余部分,这绝非易事。分割字符串的方法不止几种,还有更多更优雅的方法,但一个暴力的例子会给你一个想法。你可以把它整理成你认为合适的样子。只需通过更改dwidth变量或在文件名后提供所需的宽度作为第二个参数来设置宽度。

这假设您的输入格式与您描述的一样,字段由tabs分隔,例如:#tDescriptiontAmounttPricetSum

#!/bin/bash
test -r "$1" || { 
    printf "Error: insufficient input, usage ${0//*//} <orders file>nn"
    exit 1
}
oifs=$IFS           # set IFS to only break on tab or newline
IFS=$'tn'
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 %-8sn" $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 "   %-*sn" $dwidth "${desc:$strt:$i}"   # print to width
            else
                printf "   %-*sn" $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 %-8sn" $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€

相关内容

  • 没有找到相关文章

最新更新