首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Linux中如何在列中换行

在Linux中如何在列中换行
EN

Stack Overflow用户
提问于 2019-06-27 01:58:27
回答 2查看 442关注 0票数 2

我有一个逗号分隔的文件,我正在使用printf格式化它以创建2列。我使用awk将内容分组到类似的组中,这样我就可以将它们打印到格式良好的列中。

格式化是有效的,但是数组的内容换行到新行上,而不是在列本身内换行。

输入文件示例:

代码语言:javascript
复制
1,test,test1,test1
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2
2,test,test1,test2`

使用的命令:

代码语言:javascript
复制
awk -F"," 'NR>1 {a[$3]=a[$3] ? a[$3]", "$4" ("$2")" : $4" ("$2")"}
  END {for (i in a) {print i":"a[i]}}' test.dat |
sort |
awk -F":" 'BEGIN { printf "%-15s %-10s\n", "COLUMN1","COLUMN2"; printf "%-15s %-10s\n", "-----------","----------"}
  { printf "%-15s %-10s\n", $1,$2}'

我也知道并尝试过使用column -t -s","pr

结果如下(模拟示例):

代码语言:javascript
复制
COLUMN1     COLUMN2
========     =======
1            test1
2            test2, test2, test2, test2, test2, test2,test2, test2, test2,test2, test2, test2, test2, test2

我如何包装第二列(如果它太长,甚至第一列也是如此),以便它适合它的框架?

代码语言:javascript
复制
COLUMN1     COLUMN2
========     =======
1            test1
2            test2, test2, test2, test2, test2, test2,test2, test2, 
             test2,test2, test2, test2, test2, test2
EN

回答 2

Stack Overflow用户

发布于 2019-06-27 03:44:12

让我们假设这就是您的原始脚本正在做的事情,给定您发布的样本输入和您所获得的输出:

代码语言:javascript
复制
$ cat tst.awk
BEGIN { FS=","; OFS="\t" }
{ vals[$1] = ($1 in vals ? vals[$1] ", " : "") $4 }
END {
    print "column1", "column2"
    print "=======", "======="

    for (key in vals) {
        print key, vals[key]
    }
}

$ awk -f tst.awk file
column1 column2
======= =======
1       test1
2       test2, test2, test2, test2, test2, test2, test2, test2, test2, test2, test2, test2

这是你的问题的一个很好的起点,现在你想要包装每一列吗?如果是这样的话,我将利用现有的UNIX工具(如foldfmt )为您完成包装,这样您就不必编写自己的代码来处理空格和中间字的拆分,等等:

代码语言:javascript
复制
$ cat tst.awk
BEGIN { FS=","; OFS="\t" }
{ vals[$1] = ($1 in vals ? vals[$1] ", " : "") $4 }
END {
    print "column1", "column2"
    print "=======", "======="

    for (key in vals) {
        numKeyLines = wrap(key,15,keyArr)
        numValLines = wrap(vals[key],50,valArr)
        numLines = (numKeyLines > numValLines ? numKeyLines : numValLines)
        for (lineNr=1; lineNr<=numLines; lineNr++) {
            print keyArr[lineNr], valArr[lineNr]
        }
    }
}

function wrap(inStr,wid,outArr,         cmd,line,numLines) {
    if ( length(inStr) > wid ) {
        cmd = "printf \047%s\n\047 \"" inStr "\" | fold -s -w " wid+0
        while ( (cmd | getline line) > 0 ) {
            outArr[++numLines] = line
        }
        close(cmd)
    }
    else {
        outArr[++numLines] = inStr
    }
    return numLines+0
}

代码语言:javascript
复制
$ awk -f tst.awk file
column1 column2
======= =======
1       test1
2       test2, test2, test2, test2, test2, test2, test2,
        test2, test2, test2, test2, test2

如果你有很多字段需要包装,那么它将不会很快,因为每次调用fold都会产生一个子外壳,所以这里是一个all awk版本,尽可能在空格中拆分,测试它的边缘情况并根据需要进行按摩:

代码语言:javascript
复制
$ cat tst.awk
BEGIN { FS=","; OFS="\t" }
{ vals[$1] = ($1 in vals ? vals[$1] ", " : "") $4 }
END {
    print "column1", "column2"
    print "=======", "======="

    for (key in vals) {
        numKeyLines = wrap(key,15,keyArr)
        numValLines = wrap(vals[key],50,valArr)
        numLines = (numKeyLines > numValLines ? numKeyLines : numValLines)
        for (lineNr=1; lineNr<=numLines; lineNr++) {
            print keyArr[lineNr], valArr[lineNr]
        }
    }
}

function wrap(inStr,wid,outArr,         lineEnd,numLines) {
    while ( length(inStr) > wid ) {
        lineEnd = ( match(substr(inStr,1,wid),/.*[[:space:]]/) ? RLENGTH - 1 : wid )
        outArr[++numLines] = substr(inStr,1,lineEnd)
        inStr = substr(inStr,lineEnd+1)
        sub(/^[[:space:]]+/,"",inStr)
    }
    outArr[++numLines] = inStr
    return numLines
}

$ awk -f tst.awk file
column1 column2
======= =======
1       test1
2       test2, test2, test2, test2, test2, test2, test2,
        test2, test2, test2, test2, test2
票数 2
EN

Stack Overflow用户

发布于 2019-06-27 06:08:25

下面是一个使用perl而不是awk的版本:

代码语言:javascript
复制
#!/usr/bin/env perl
use warnings;
use strict;

my ($col1, $col4, @col4data);

print <<EOF;
COLUMN1     COLUMN2
=======     =======
EOF

{
  my $line = <>;
  chomp $line;
  ($col1, $col4data[0]) = (split /,/, $line)[0,3];
}

while (<>) {
  chomp;
  my ($c, $a) = (split /,/)[0,3];
  if ($c ne $col1) {
    $col4 = join ", ", @col4data;
    write;
    @col4data = ();
    $col1 = $c;
  }
  push @col4data, $a;
}

$col4 = join ", ", @col4data;
write;

format STDOUT =
@<<<<<<<    ^<<<<<<<<<<<<<<<<<<<<<<
$col1,      $col4
~~          ^<<<<<<<<<<<<<<<<<<<<<<
            $col4
.

示例:

代码语言:javascript
复制
$ perl columns.pl input.csv
COLUMN1     COLUMN2
=======     =======
1           test1
2           test2, test2, test2,
            test2, test2, test2,
            test2, test2, test2,
            test2, test2, test2

这里的魔术是使用output format的填充模式进行换行,通过在format描述中明显的部分添加更多的<来根据需要调整宽度。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56778612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档