我有一个看起来像的文件:
SECTION1 id name
sub section1
sub section2
SECTION2 id name
sub section3
sub section4
sub section6
SECTION1 id name
sub section7
sub section8
SECTION3 id name
sub section9
sub section10
sub section11
sub section12
SECTION2 id name
sub section13
sub section14
SECTION1 id name
sub section15
sub section16
SECTION3 id name
sub section17
sub section18
我需要明智地对此文件进行排序。我唯一知道的是我有'SECTION1','SECTION2'和'SECTION3'。 排序后的预期输出为:
SECTION1 id name
sub section1
sub section2
SECTION1 id name
sub section7
sub section8
SECTION1 id name
sub section15
sub section16
SECTION2 id name
sub section3
sub section4
sub section6
SECTION2 id name
sub section13
sub section14
SECTION3 id name
sub section9
sub section10
sub section11
sub section12
SECTION3 id name
sub section17
sub section18
在perl中使用grep,sed等实用程序有没有简单的方法?
答案 0 :(得分:3)
使用perl
的另一种方式:
假设infile
包含问题的内容以及script.pl
的以下内容:
use warnings;
use strict;
use sort qw/stable/;
my ($section, @section);
while ( <> ) {
## Save text if first line or when line doesn't begin with 'SECTION' word.
if ( $. == 1 || $_ !~ m/\ASECTION\d+/ ) {
$section .= $_;
next unless eof;
}
## Save the text and the number of section.
if ( $section =~ m/\ASECTION(\d+)/ ) {
push @section, [ $1, $section ];
$section = q||;
}
## Begin to save next section.
$section .= $_;
}
## Print them sorted by section number.
for ( sort { $a->[0] <=> $b->[0] } @section ) {
printf qq|%s|, $_->[1];
}
像以下一样运行:
perl script.pl infile
使用以下输出:
SECTION1 id name
sub section1
sub section2
SECTION1 id name
sub section7
sub section8
SECTION1 id name
sub section15
sub section16
SECTION2 id name
sub section3
sub section4
sub section6
SECTION2 id name
sub section13
sub section14
SECTION3 id name
sub section9
sub section10
sub section11
sub section12
SECTION3 id name
sub section17
sub section18
答案 1 :(得分:3)
看起来像需要特殊排序的东西。 Perl的默认排序无法使用数字正确排序字符串,因此我们需要在排序之前提取数字。如果是大数据集,我使用Schwartzian transform优化它。
它的基本要点是首先提取部分编号,然后是子部分编号,然后先对部分编号进行排序,如果是平局,则对子部分编号进行排序。仅考虑子节中的第一个数字,因此它假定这些行已经排序。
要在文件中使用它,只需将<DATA>
更改为<>
,然后运行:
perl script.pl inputfile > outputfile
<强>代码:强>
use strict;
use warnings;
local $/; # read entire file
my $data = <DATA>; # slurp input file into scalar
my @records = split /(?=^SECTION)/m, $data; # split into records
my @sorted = map { $_->[0] }
sort { $a->[1] <=> $b->[1] ||
$a->[2] <=> $b->[2] }
map { getnum($_) } @records; # Schwartzian transform sort
print @sorted;
sub getnum { # extract section and subsection numbers
my ($sec) = $_[0] =~ /SECTION(\d+)/;
my ($sub) = $_[0] =~ /\n.*?(\d+)/;
return [ $_[0], $sec, $sub ]; # return anonymous array
}
__DATA__
SECTION1 id name
sub section1
sub section2
SECTION2 id name
sub section3
sub section4
sub section6
SECTION1 id name
sub section7
sub section8
SECTION3 id name
sub section9
sub section10
sub section11
sub section12
SECTION2 id name
sub section13
sub section14
SECTION1 id name
sub section15
sub section16
SECTION3 id name
sub section17
sub section18
答案 2 :(得分:1)
#!/usr/bin/perl
use strict;
use warnings;
my @data;
{ # limit change to $/ to this scope
local $/ = "SECTION";
@data = map {chomp; $_ || ()} <DATA>;
}
{ # limit change to 'warnings' to this scope
no warnings 'numeric';
print "SECTION$_" for sort {$a <=> $b} @data;
}
这将保留各个部分。
或者从命令行:
perl -F/SECTION/ -0ane "print qq{SECTION$_} for grep $_, sort {$a <=> $b} @F" o33.txt
答案 3 :(得分:1)
这可能适合你(GNU sed):
sed ':a;$!N;/\nSECTION/!s/\n/\x00/;ta;s/n\([0-9][\x00\n]\|$\)/n0\1/g;P;D' file |
sort |
sed 's/\x00/\n/g;s/n0/n/g'
说明:
SECTIONs
和sub sections
加入单行。 :a;$!N;/\nSECTION/!s/\n/\x00/;ta
0
添加到sub sections
。 s/n\([0-9][\x00\n]\|$\)/n0\1/g
P;D
sort
sed 's/\x00/\n/g;s/n0/n/g'
答案 4 :(得分:1)
这很简单,只需根据章节标签在三个sparate列表中累积记录即可。
此程序使用哈希来执行此操作,并通过将文件中的每一行附加到最新记录来构建完整的部分。如果该行是新部分的开头,则在追加该行之前将另一个空记录添加到列表中。
显示结果只是按照部分标签的顺序打印列表的所有元素。
use strict;
use warnings;
open my $fh, '<', 'sections.txt' or die $!;
my %sections;
my $current_list;
while (<$fh>) {
if (/^(SECTION[123])/) {
$current_list = $sections{$1} //= [];
push @$current_list, '';
}
$current_list->[-1] .= $_ if $current_list;
}
for my $name (sort keys %sections) {
print for @{ $sections{$name} };
}
<强>输出强>
SECTION1 id name
sub section1
sub section2
SECTION1 id name
sub section7
sub section8
SECTION1 id name
sub section15
sub section16
SECTION2 id name
sub section3
sub section4
sub section6
SECTION2 id name
sub section13
sub section14
SECTION3 id name
sub section9
sub section10
sub section11
sub section12
SECTION3 id name
sub section17
sub section18