【发布时间】:2021-03-04 22:00:18
【问题描述】:
我想将每个偶数行与它上面的行合并。比如:
第一行,csv,csv,csv 第二行,csv,csv 第三行,csv,csv,csv,csv 第四行,csv
结果应该是这样的:
第一行,csv,csv,csv,第二行,csv,csv 第三行,csv,csv,csv,csv,第四行,csv
任何想法如何在 Perl 或 sed/awk 中实现这一目标?
【问题讨论】:
标签: text
我想将每个偶数行与它上面的行合并。比如:
第一行,csv,csv,csv 第二行,csv,csv 第三行,csv,csv,csv,csv 第四行,csv
结果应该是这样的:
第一行,csv,csv,csv,第二行,csv,csv 第三行,csv,csv,csv,csv,第四行,csv
任何想法如何在 Perl 或 sed/awk 中实现这一目标?
【问题讨论】:
标签: text
在这里,使用 sed:
sed '$!N;s/\n/,/'
和 awk:
awk '{if (e) {print p","$0;} else {p=$0;} e=!e;}'
或
awk 'NR%2==0 {print p","$0;} NR%2 {p=$0;}'
【讨论】:
perl -pe '$|--||s!$/!,!'还要短!
$. % 2 && 和 $|-- || 一样短,但没有那么特别。
$!,因为如果seds N 或n 命令尝试读取超出文件末尾的内容,它们将终止任何进一步的命令.但是,如果未设置 -n 选项,它仍会打印模式空间。
这就是paste 命令的用途。假设你的输出是用command 生成的,那么你可以这样做:
$ command | paste -d, - -
或者如果输出存储在文件中
$ paste -d, - - <file.csv
例子:
paste -d, - - <<END
Line one,csv,csv,csv
Line two,csv,csv
Line three,csv,csv,csv,csv
Line four,csv
END
输出:
Line one,csv,csv,csv,Line two,csv,csv
Line three,csv,csv,csv,csv,Line four,csv
【讨论】:
process_to_produce_output 应该是什么来解决这个问题。更多细节?
info paste会给你一个教程。
paste 将文件行合并在一起,使用默认的 TAB 分隔符。如果您将- 指定为文件,它会将其解释为STDIN。所以paste -d, - - 的意思是:合并来自STDIN 和STDIN 的行,使用, 作为分隔符而不是TAB。如果你使用paste -d, - - -,它将每3行连接在一起,- - - -将每4行连接在一起,依此类推。
还有一个:
awk -F, ORS=NR%2\?FS:RS infile
您不需要引用 ?大多数shell。
【讨论】:
Perl 的内置变量$. 会告诉你行号。如果$. 为奇数,$. % 2 将为1,否则为0。这是一个独立的示例;
#!/usr/bin/perl
use strict; use warnings;
my $buffer;
while (my $line = <DATA>) {
if ($. % 2) {
chomp $line;
$buffer = $line;
}
else {
print join(",", $buffer, $line);
}
}
__DATA__
Line one,csv,csv,csv
Line two,csv,csv
Line three,csv,csv,csv,csv
Line four,csv
输出:
C:\Temp> tt 第一行,csv,csv,csv,第二行,csv,csv 第三行,csv,csv,csv,csv,第四行,csv
【讨论】:
通常,您会在缓冲区中累积数据,直到您知道要输出什么,然后再输出数据。
my @buf;
while (<>) {
chomp;
if (!@buf) {
push @buf, $_;
next;
}
my $line1 = shift(@buf);
my $line2 = $_;
print("$line1,$line2\n");
}
但在这种情况下,存在一个更简单的解决方案,因为您的问题可以重述为:用逗号替换每个第二个换行符,从第一个换行符开始。
perl -pe's/\n/,/ if $. % 2' file
【讨论】:
一个稍微简单的 Perl 解决方案。
#!/usr/bin/perl
use strict;
use warnings;
while (<DATA>) {
chomp;
print "$_," . <DATA>;
}
__DATA__
Line one,csv,csv,csv
Line two,csv,csv
Line three,csv,csv,csv,csv
Line four,csv
【讨论】:
你不需要像 perl/sed/awk 这样的核武器来解决这个问题。
xargs 就够了。
xargs -d '\n' -n2
测试
kent$ echo "Line one,csv,csv,csv
Line two,csv,csv
Line three,csv,csv,csv,csv
Line four,csv"|xargs -d '\n' -n2
Line one,csv,csv,csv Line two,csv,csv
Line three,csv,csv,csv,csv Line four,csv
【讨论】: