连接线,以记录数为模
Joining lines, modulo the number of records
假设我的流是 x*N 行长,其中 x 是记录数,N 是每条记录的列数,并且按列输出。例如,x=2, N=3:
1
2
Alice
Bob
London
New York
如何连接每一行,以记录数为模,返回列:
1 Alice London
2 Bob New York
如果我使用 paste
,N -
s,我得到转置输出。我可以使用 split
,-l
选项等于 N,然后用 paste
重新组合这些片段,但我想在流中进行,而不吐出所有临时文件在这个地方。
是否有 "easy" 解决方案(即,而不是调用类似 awk 的方法)?我在想可能有一些神奇的 join
解决方案,但我看不到它...
EDIT 另一个例子,当 x=5 和 N=3 时:
1
2
3
4
5
a
b
c
d
e
alpha
beta
gamma
delta
epsilon
预期输出:
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilon
为了可靠地处理输入,您需要知道输出文件中的列数或输出文件中的行数。如果您只知道列数,则需要读取输入文件两次。
Hackish coreutils 解决方案
# If you don't know the number of output lines but the
# number of output columns in advance you can calculate it
# using wc -l
# Split the file by the number of output lines
split -l"${olines}" file FOO # FOO is a prefix. Choose a better one
paste FOO*
AWK 解决方案
如果您事先知道输出列的数量,您可以使用这个 awk
脚本:
convert.awk:
BEGIN {
# Split the file into one big record where fields are separated
# by newlines
RS=''
FS='\n'
}
FNR==NR {
# We are reading the file twice (see invocation below)
# When reading it the first time we store the number
# of fields (lines) in the variable n because we need it
# when processing the file.
n=NF
}
{
# n / c is the number of output lines
# For every output line ...
for(i=0;i<n/c;i++) {
# ... print the columns belonging to it
for(ii=1+i;ii<=NF;ii+=n/c) {
printf "%s ", $ii
}
print "" # Adds a newline
}
}
并这样称呼它:
awk -vc=3 -f convert.awk file file # Twice the same file
如果您事先知道输出行数,您可以使用以下 awk
脚本:
convert.awk:
BEGIN {
# Split the file into one big record where fields are separated
# by newlines
RS=''
FS='\n'
}
{
# x is the number of output lines and has been passed to the
# script. For each line in output
for(i=0;i<x;i++){
# ... print the columns belonging to it
for(ii=i+1;ii<=NF;ii+=x){
printf "%s ",$ii
}
print "" # Adds a newline
}
}
并这样称呼它:
awk -vx=2 -f convert.awk file
您正在寻找 pr
到 "columnate" 的信息流:
pr -T -s$'\t' -3 <<'END_STREAM'
1
2
Alice
Bob
London
New York
END_STREAM
1 Alice London
2 Bob New York
pr
在 coreutils 中。
大多数系统应该包含一个名为 pr
的工具,用于 print 文件。它是 part of POSIX.1,因此几乎可以肯定它会出现在您将使用的任何系统上。
$ pr -3 -t < inp1
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilon
或者,如果您愿意,
$ pr -3 -t -s, < inp1
1,a,alpha
2,b,beta
3,c,gamma
4,d,delta
5,e,epsilon
或
$ pr -3 -t -w 20 < inp1
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilo
查看上面的 link 以获取标准使用信息,或查看 man pr
以获取您操作系统中的特定选项。
假设我的流是 x*N 行长,其中 x 是记录数,N 是每条记录的列数,并且按列输出。例如,x=2, N=3:
1
2
Alice
Bob
London
New York
如何连接每一行,以记录数为模,返回列:
1 Alice London
2 Bob New York
如果我使用 paste
,N -
s,我得到转置输出。我可以使用 split
,-l
选项等于 N,然后用 paste
重新组合这些片段,但我想在流中进行,而不吐出所有临时文件在这个地方。
是否有 "easy" 解决方案(即,而不是调用类似 awk 的方法)?我在想可能有一些神奇的 join
解决方案,但我看不到它...
EDIT 另一个例子,当 x=5 和 N=3 时:
1
2
3
4
5
a
b
c
d
e
alpha
beta
gamma
delta
epsilon
预期输出:
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilon
为了可靠地处理输入,您需要知道输出文件中的列数或输出文件中的行数。如果您只知道列数,则需要读取输入文件两次。
Hackish coreutils 解决方案
# If you don't know the number of output lines but the
# number of output columns in advance you can calculate it
# using wc -l
# Split the file by the number of output lines
split -l"${olines}" file FOO # FOO is a prefix. Choose a better one
paste FOO*
AWK 解决方案
如果您事先知道输出列的数量,您可以使用这个 awk
脚本:
convert.awk:
BEGIN {
# Split the file into one big record where fields are separated
# by newlines
RS=''
FS='\n'
}
FNR==NR {
# We are reading the file twice (see invocation below)
# When reading it the first time we store the number
# of fields (lines) in the variable n because we need it
# when processing the file.
n=NF
}
{
# n / c is the number of output lines
# For every output line ...
for(i=0;i<n/c;i++) {
# ... print the columns belonging to it
for(ii=1+i;ii<=NF;ii+=n/c) {
printf "%s ", $ii
}
print "" # Adds a newline
}
}
并这样称呼它:
awk -vc=3 -f convert.awk file file # Twice the same file
如果您事先知道输出行数,您可以使用以下 awk
脚本:
convert.awk:
BEGIN {
# Split the file into one big record where fields are separated
# by newlines
RS=''
FS='\n'
}
{
# x is the number of output lines and has been passed to the
# script. For each line in output
for(i=0;i<x;i++){
# ... print the columns belonging to it
for(ii=i+1;ii<=NF;ii+=x){
printf "%s ",$ii
}
print "" # Adds a newline
}
}
并这样称呼它:
awk -vx=2 -f convert.awk file
您正在寻找 pr
到 "columnate" 的信息流:
pr -T -s$'\t' -3 <<'END_STREAM'
1
2
Alice
Bob
London
New York
END_STREAM
1 Alice London
2 Bob New York
pr
在 coreutils 中。
大多数系统应该包含一个名为 pr
的工具,用于 print 文件。它是 part of POSIX.1,因此几乎可以肯定它会出现在您将使用的任何系统上。
$ pr -3 -t < inp1
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilon
或者,如果您愿意,
$ pr -3 -t -s, < inp1
1,a,alpha
2,b,beta
3,c,gamma
4,d,delta
5,e,epsilon
或
$ pr -3 -t -w 20 < inp1
1 a alpha
2 b beta
3 c gamma
4 d delta
5 e epsilo
查看上面的 link 以获取标准使用信息,或查看 man pr
以获取您操作系统中的特定选项。