如何在Linux中的列中换行 [英] How to wrap lines within columns in Linux

查看:107
本文介绍了如何在Linux中的列中换行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a comma delimited file which I am formatting to create 2 columns using printf. I am using awk to group the contents into similar groups so I can print them into nicely formatted columns.

格式化是可行的,但是数组的内容会换行,而不是换入列本身.

The formatting works but the contents of the array wrap onto new lines instead of wrapping within the column itself.

输入文件示例:

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`

使用的命令:

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

I am also aware about and have tried using column -t -s"," and pr

结果类似于(模拟示例):

The outcome is like (simulating example):

COLUMN1     COLUMN2
========     =======
1            test1
2            test2, test2, test2, test2, test2, test2,test2, test2, test2,test2, test2, test2, test2, test2

如何包装第二列(如果它太长,即使第一列也是如此)以使其适合其框架?

How can I wrap the second column (even the first one if it is too long) so that it fits within its frame?

COLUMN1     COLUMN2
========     =======
1            test1
2            test2, test2, test2, test2, test2, test2,test2, test2, 
             test2,test2, test2, test2, test2, test2

推荐答案

假设您发布的示例输入和您说得到的输出,假装这是您原始脚本正在做的事情:

Let's pretend this is what your original script is doing given your posted sample input and the output you say you get:

$ 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)为您打包,因此您不必编写自己的代码来处理空格与中间单词等的拆分. :

Would that be a good starting point for your question and now you want to wrap each column? If so then I'd take advantage of an existing UNIX tool like fold or fmt to do the wrapping for you so you don't have to write your own code to handle splitting on spaces vs mid-word, etc.:

$ 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
}

.

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

如果您有很多需要包装的字段,那么由于每次调用fold都会生成一个子shell,所以它不会很快,所以这里是一个全awk版本,它会在可能的情况下拆分为空格,请对其进行测试边缘情况和适合的按摩:

If you have a lot of fields that need to be wrapped then it won't be fast due to spawning a subshell for each call to fold so here's an all awk version that splits at spaces when possible, test it for edge cases and massage to suit:

$ 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

这篇关于如何在Linux中的列中换行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆