如何使用 awk 或 sed 将几行转置为列
how to transpose few rows to column using awk or sed
我想把一行中的一些数据放到当前列的侧列,。列的块 1 和块 2 由新行分隔。我该怎么做。
Cat filename
aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
cat desiredFile
aaa eee
bbb fff
ccc ggg
ddd hhh
方法有很多种。使用 bash、粘贴和 GNU sed 的简单方法是
paste -d ' ' <(sed '/^$/Q' filename) <(sed '0,/^$/d' filename)
这里
sed '/^$/Q' filename
打印文件中直到第一个空行的所有行
sed '0,/^$/d' filename
打印第一个空行后的所有行
<()
是一个特定于 bash 的进程替换,它扩展为可以读取命令输出的管道名称(因此它可以用作输入文件名), 和
paste -d ' ' file1 file2
按照您描述的方式将两个文件粘贴在一起(由于 -d ' '
由 space 分隔;如果没有该选项,它将使用制表符)
或者你可以使用 awk:
awk -v RS="" -F '\n' 'NF > n { n = NF } { for(i = 1; i <= NF; ++i) a[i] = a[i] OFS $i } END { for(i = 1; i <= n; ++i) print a[i] }' filename
对于空 RS
,awk 在空行处将文件拆分为记录,对于 -F '\n'
,它在换行符处将这些记录拆分为字段,然后代码为
# remember maximum number of fields encountered
NF > n { n = NF }
# wade through the fields, assemble the output lines from them
{ for(i = 1; i <= NF; ++i) a[i] = a[i] OFS $i }
# in the end, print the assembled lines.
END { for(i = 1; i <= n; ++i) print a[i] }
awk 方法的优势在于它可以处理两段以上的行。
Ruby 对于单行代码很方便,它有一个内置的转置方法。使用与 Wintermute 类似的方法,我们有:
ruby -00 -F"\n" -ane '
BEGIN {data=[]}
data << $F
END {data.transpose.each {|row| puts row.join(" ")}}
' file
我在测试文件中又添加了一段,它的输出是这样的:
aaa eee iii
bbb fff jjj
ccc ggg kkk
ddd hhh lll
$ cat tst.awk
BEGIN { numCols=1 }
!NF { numRows=0; ++numCols; next }
{ a[++numRows,numCols]=[=10=] }
END {
for (r=1;r<=numRows;r++) {
for (c=1;c<=numCols;c++) {
printf "%s%s", a[r,c], (c<numCols?OFS:ORS)
}
}
}
$ awk -f tst.awk file
aaa eee
bbb fff
ccc ggg
ddd hhh
我想把一行中的一些数据放到当前列的侧列,。列的块 1 和块 2 由新行分隔。我该怎么做。
Cat filename
aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
cat desiredFile
aaa eee
bbb fff
ccc ggg
ddd hhh
方法有很多种。使用 bash、粘贴和 GNU sed 的简单方法是
paste -d ' ' <(sed '/^$/Q' filename) <(sed '0,/^$/d' filename)
这里
sed '/^$/Q' filename
打印文件中直到第一个空行的所有行sed '0,/^$/d' filename
打印第一个空行后的所有行<()
是一个特定于 bash 的进程替换,它扩展为可以读取命令输出的管道名称(因此它可以用作输入文件名), 和paste -d ' ' file1 file2
按照您描述的方式将两个文件粘贴在一起(由于-d ' '
由 space 分隔;如果没有该选项,它将使用制表符)
或者你可以使用 awk:
awk -v RS="" -F '\n' 'NF > n { n = NF } { for(i = 1; i <= NF; ++i) a[i] = a[i] OFS $i } END { for(i = 1; i <= n; ++i) print a[i] }' filename
对于空 RS
,awk 在空行处将文件拆分为记录,对于 -F '\n'
,它在换行符处将这些记录拆分为字段,然后代码为
# remember maximum number of fields encountered
NF > n { n = NF }
# wade through the fields, assemble the output lines from them
{ for(i = 1; i <= NF; ++i) a[i] = a[i] OFS $i }
# in the end, print the assembled lines.
END { for(i = 1; i <= n; ++i) print a[i] }
awk 方法的优势在于它可以处理两段以上的行。
Ruby 对于单行代码很方便,它有一个内置的转置方法。使用与 Wintermute 类似的方法,我们有:
ruby -00 -F"\n" -ane '
BEGIN {data=[]}
data << $F
END {data.transpose.each {|row| puts row.join(" ")}}
' file
我在测试文件中又添加了一段,它的输出是这样的:
aaa eee iii
bbb fff jjj
ccc ggg kkk
ddd hhh lll
$ cat tst.awk
BEGIN { numCols=1 }
!NF { numRows=0; ++numCols; next }
{ a[++numRows,numCols]=[=10=] }
END {
for (r=1;r<=numRows;r++) {
for (c=1;c<=numCols;c++) {
printf "%s%s", a[r,c], (c<numCols?OFS:ORS)
}
}
}
$ awk -f tst.awk file
aaa eee
bbb fff
ccc ggg
ddd hhh