2016-08-05 51 views
0

我有一个input.csv文件,第2列和第3列中有变量lengtt。如何使用awk或sed调整bash中的列字段的长度?

100,Short Column, 199 
200,Meeedium Column,1254 
300,Loooooooooooong Column,35 

我尝试使用下面的命令来实现一个干净的列表,但我需要填充一定数量的空格的第2列,以获得一个固定的lenght柱(比方说,一个总长度为30就足够了)。

awk -F, '{print $1 "\t" $2 "\t" $3;}' input.csv 

我的电流输出是这样的:

100 Short Column 199 
200 Meeedium Column 1254 
300 Loooooooooooong Column 35 

而且我想实现下面的输出,通过填充第二,妥善第3列:

100 Short Column    199 
200 Meeedium Column   1254 
300 Loooooooooooong Column  35 

什么好主意了那里应该使用awk或sed命令? 谢谢大家。

+3

'列-t input.csv'或看看'printf'或'awk'的' printf'。 – Cyrus

+0

'列-s,-t文件'应该这样做 – anubhava

+1

@anubhava:谢谢。 – Cyrus

回答

1

而不是采摘一些任意数作为每个字段的宽度的解决方案,因为,那里的第一遍计算每个字段的最大长度和第二打印的字段的2步方法在尺寸加场之间的耦合的空格的宽度:

$ cat tst.awk 
BEGIN { FS=" *, *"; OFS=" " } 
NR==FNR { 
    for (i=1;i<=NF;i++) { 
     w[i] = (length($i) > w[i] ? length($i) : w[i]) 
     if ($i ~ /[^0-9]/) { 
      a[i] = "-" 
     } 
    } 
    next 
} 
{ 
    for (i=1;i<=NF;i++) { 
     printf "%"a[i]w[i]"s%s", $i, (i<NF ? OFS : ORS) 
    } 
} 

$ awk -f tst.awk file file 
100 Short Column    199 
200 Meeedium Column   1254 
300 Loooooooooooong Column 35 

上面还使用左对准用于非数字字段,对于所有的位数字段右对齐。它会工作,不管输入字段有多长,也不管你有多少领域有:

$ cat file1 
100000,Short Column, 199,a 
100,Now is the Winter of our discontent with fixed width fields,20000,b 
100,Short Column, 199,c 
200,Meeedium Column,1254,d 
300,Loooooooooooong Column,35,e 

$ awk -f tst.awk file1 file1 
100000 Short Column             199 a 
    100 Now is the Winter of our discontent with fixed width fields 20000 b 
    100 Short Column             199 c 
    200 Meeedium Column            1254 d 
    300 Loooooooooooong Column           35 e 
+1

辉煌的解决方案。是否有任何方法可以自定义tst.awk(或bash中的命令行)以便开始仅针对某些特定列进行对齐?例如:在包含30列的csv中,我希望仅将对齐应用于第20,21,22列(因为从1到19的列仅仅是我希望从打印中丢弃的标题)。 –

+0

当然,只需将'1'更改为您的起始字段编号和'NF'即可。如果你喜欢,用'-v'设置变量来传入这些开始/结束值。如果你无法弄清楚,试试它并发布一个新的跟进问题。如果您发布了这个问题的答案,请记住通过点击旁边的复选标记来接受您选择的那个(请参阅http://stackoverflow.com/help/someone-answers)。 –

+0

感谢您的提示,剧本完美无缺!我想知道是否有任何方法可以修改tst.awk脚本,以便为数字字段进行正确对齐,也可以在小数点的情况下使用。目前,脚本在右侧对齐数量1000,但左侧数量为1000.99(实际上这是我的错误,我没有在我的问题中指定数字字段包含小数)。可能我应该添加一些代码到你的行开始以下:if($ i〜/ [^ 0-9] /)。再次感谢你,一些代码! –

2

使用printfawk

$ awk -F, '{gsub(/ /, "", $3); printf "%-5s %-25s%5s\n", $1, $2, $3}' file input.csv 
100 Short Column    199 
200 Meeedium Column   1254 
300 Loooooooooooong Column  35 

我在上面所做的,设置了IFS,字段分隔符,;由于该文件在第三列中仅有一些空格,因此它会损坏,printf如何处理字符串,如何使用gsub将其删除,并使用C风格printf进行格式化。

+1

或用bash的printf:'while IFS =,read -r a b c;做printf“%5s%-25s%5s \ n”“$ a”“$ b”“$ c”;完成 Cyrus

+0

@Inian好的代码!谢谢。是否有任何方法可以自定义awk以便开始仅针对某些特定列进行对齐?例如:在一个有30列的csv中,我希望仅将对齐方式应用于第20,21,22列(因为第1至19列和第23至30列仅仅是我希望从打印中丢弃的页眉/页脚)。 –

0

使用perl

$ perl -pe 's/([^,]+),([^,]+),([^,]+)/sprintf "%-6s%-30s%5s", $1,$2,$3/e' input.csv 
100 Short Column     199 
200 Meeedium Column    1254 
300 Loooooooooooong Column   35