2

特定の列幅を使用して CSV ファイルを印刷しようとしています。最初の列が印刷されない原因となる i のエラーが 1 つずれていると思います。ご覧のとおり、私は bash を初めて使用し、必死に C のように動作させようとしています。

CSV='./test.csv'
column_width=(20 6 5 10 10 10 10 8 30)

IFS=","
        while read LINE
        do
                set -- $LINE
                arg=($@)
                for (( i = 0 ; i < ${#arg[@]} ; i++))
                do
                        case $i in
                                1) printf "%-20s"   ${arg[$i]} ;;
                                2) printf "%-6s"    ${arg[$i]} ;;
                                3) printf "%-5s"    ${arg[$i]} ;;
                                4) printf "%-10s"   ${arg[$i]} ;;
                                5) printf "%-10s"   ${arg[$i]} ;;
                                6) printf "%-10s"   ${arg[$i]} ;;
                                7) printf "%-10s"   ${arg[$i]} ;;
                                8) printf "%-8s"    ${arg[$i]} ;;
                                9) printf "%-30s\n" ${arg[$i]} ;;
                        esac
                done
        done < $CSV
        unset IFS

ケースステートメントをループに変えるのにも問題があります。役に立たなかったので、C スタイルの for ループ全体を次のように置き換えてみました。

for i in "${arg[@]}"; do
        printf "%-${column_width[$i]}s" ${arg[$i]}
done

これを達成するためのより良い方法があると確信しています。私はsed/awkについて学ぼうとしていますが、今のところそれらなしでそれを行う方法を知りたいです.

4

3 に答える 3

2
#!/usr/bin/env bash

csv=./test.csv
column_width=(20 6 5 10 10 10 10 8 30)

while n=0; IFS=, read -ra x; do
    printf '%-*s' {,,,,,,,,}{"${column_width[n]}","${x[n++]}"} 1 $'\n'
done <"$csv"
于 2012-07-04T08:06:40.063 に答える
2

スクリプトは非常にエレガントだと思います。どの言語でもこれをより簡潔に行うのは難しいでしょう (ただし、これは私が好きではないバシズムを使用します :->)

私はスクリプトロジックを回避し、エディターのマクロ機能を使用する側にいるので、ここに私のバージョンがあります。

#!/bin/sh

CSV='./test.csv'

while IFS=, read one two three four five six seven eight nine
do
    test "$one"   && printf %s-20s "$one"
    test "$two"   && printf %s-6s  "$two"
    test "$three" && printf %s-5s  "$three"
    test "$four"  && printf %s-10s "$four"
    test "$five"  && printf %s-10s "$five"
    test "$six"   && printf %s-10s "$six"
    test "$seven" && printf %s-10s "$seven"
    test "$eight" && printf %s-8s  "$eight"
    test "$nine"  && printf %s-30s "$nine"
    printf \\n
done < "$CSV"   # mind the quoting

個人的には、見た目はもう少し快適だと思います(そしてバシズムはありません!)が、YMMV. 大規模なテストも避けたいと思いますが、可能であれば印刷するだけです。

于 2012-07-04T00:01:53.130 に答える
1

よくやった、コントラポジティブ。

スクリプトの off-by-one エラーは、Bash でも配列インデックスが 0 で始まるためですが、switch ケースはそうではありません。私が考えることができる最小の変更は、配列を「シフト」することargです。を使ってみてくださいarg=(0 $@)。配列の 0 番目のインデックスで他の値を使用できます。存在しない 0 の場合は処理されます。

于 2012-07-04T02:06:44.207 に答える