【发布时间】:2015-06-21 12:07:10
【问题描述】:
我想将一行中的一些数据带到当前列的侧列,。列的块 1 和块 2 由新行分隔。我该怎么做。
Cat filename
aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
cat desiredFile
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、paste 和 GNU sed 的简单方法是
paste -d ' ' <(sed '/^$/Q' filename) <(sed '0,/^$/d' filename)
这里
sed '/^$/Q' filename 打印文件中的所有行,直到第一个空行sed '0,/^$/d' filename 打印第一个空行之后的所有行<() 是一个特定于 bash 的进程替换,它扩展为可以从中读取命令输出的管道名称(以便它可以用作输入文件名),并且paste -d ' ' file1 file2 以您描述的方式将两个文件粘贴在一起(由于-d ' ' 由空格分隔;如果没有该选项,它将使用制表符)或者你可以使用 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
【讨论】:
-00 尤其感兴趣。
-0 选项将记录分隔符设置为选项参数的八进制值; -F 选项设置字段分隔符; -a 选项自动拆分记录并将字段存储在$F 数组中。 -0 有 2 个特殊值:777 禁用记录分隔并将输入作为单个字符串; 0 将输入拆分为空行序列上的记录,即“段落”。
$ cat tst.awk
BEGIN { numCols=1 }
!NF { numRows=0; ++numCols; next }
{ a[++numRows,numCols]=$0 }
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
【讨论】: