我正在尝试使用某些列宽打印CSV文件。我认为有一个错误,我导致第一列不打印。正如你将看到的,我是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
我也无法将case语句转换为循环语句。无济于事,我尝试用以下代码替换整个C风格的for循环:
for i in "${arg[@]}"; do
printf "%-${column_width[$i]}s" ${arg[$i]}
done
我确信有更好的方法来实现这一目标。我正在尝试了解sed / awk,但我想知道如何在没有它们的情况下做到这一点。
答案 0 :(得分:2)
我认为剧本非常优雅。你会很难用任何语言做到这一点(虽然这使用了我不喜欢的基础知识: - &gt;)
由于我更多关注避免脚本逻辑和使用你的编辑器的宏功能方面,所以这将是我的版本。
#!/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。我也避免进行大量测试,但如果可能的话只需打印。
答案 1 :(得分: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"
答案 2 :(得分:1)
干得好,矛盾。
脚本中的逐个错误是因为即使在Bash中的数组索引从0开始,而您的switch case也没有。我能想到的最小变化就是“移动”数组arg
。尝试使用arg=(0 $@)
。您可以在数组的第0个索引处使用任何其他值。不存在的0案件将被处理。