如何在Linux中的列中换行 [英] How to wrap lines within columns in 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工具(如fold
或fmt
)为您打包,因此您不必编写自己的代码来处理空格与中间单词等的拆分. :
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屋!