我想从Unix的文本文件中打印某些行。 要打印的行号列在另一个文本文件中(每行一个)。
Perl使用哪种POSIX正则expression式?
使用Perl DBI模块或设置系统DSN并使用ODBC会更好吗?
如何将Parallel :: ForkManager和Capture :: Tiny一起使用?
产生perl脚本在彩色控制台
假设要打印的行号被排序。
open my $fh,'<','line_numbers' or die $!; my @ln = <$fh>; open my $tx,'text_file' or die $!; foreach my $ln (@ln) { my $line; do { $line = <$tx>; } until $. == $ln and defined $line; print $line if defined $line; }
$ cat numbers 1 4 6 $ cat file one two three four five six seven $ awk 'FNR==NR{num[$1];next}(FNR in num)' numbers file one four six
您可以通过在基本while(<>)块的上下文中简单地使用eof来避免其他一些答案(对排序行的要求)的限制。 这会告诉你什么时候你停止阅读行号并开始阅读数据。 请注意,您需要重置$. 当开关发生时。
# Usage: perl script.pl LINE_NUMS_FILE DATA_FILE use strict; use warnings; my %keep; my $reading_line_nums = 1; while (<>){ if ($reading_line_nums){ chomp; $keep{$_} = 1; $reading_line_nums = $. = 0 if eof; } else { print if exists $keep{$.}; } }
猫-n foo | 加入foo2 – | 切-d“”-f2-
这里有一种方法可以在Perl中做到这一点,而不会sl anything任何东西,以使程序的内存占用与两个文件的大小无关(它假定要打印的行号是排序的):
#!/usr/bin/perl use strict; use warnings; use autodie; @ARGV == 2 or die "Supply src_file and filter_file as argumentsn"; my ($src_file,$filter_file) = @ARGV; open my $src_h,$src_file; open my $filter_h,$filter_file; my $to_print = <$filter_h>; while ( my $src_line = <$src_h> ) { last unless defined $to_print; if ( $. == $to_print ) { print $src_line; $to_print = <$filter_h>; } } close $filter_h; close $src_h;
C:> perl -le“print for aa .. zz”> src
C:> perl -le“print for grep {rand> 0.75} 1..52”> filter
C:>猫过滤器
4
6
10
12
13
19
23
24
28
44
49
50
输出:
C:> f src过滤器
广告
AF
AJ
人
上午
如
AW
斧头
BB
BR
BW
BX
while ( my $src_line = <$src_h> ) { last unless defined $to_print; if ( $. > $to_print ) { seek $src_h,0; $. = 0; } if ( $. == $to_print ) { print $src_line; $to_print = <$filter_h>; } }
如果过滤器文件的内容是相当随机的,这将浪费很多时间,因为它会一直倒转到源文件的开头。 在这种情况下,我会建议使用Tie :: File 。
我不会用大文件这样做,但(未经测试):
open(my $fh1,"<","line_number_file.txt") or die "Err: $!"; chomp(my @line_numbers = <$fh1>); $_-- for @line_numbers; close $fh1; open(my $fh2,"text_file.txt") or die "Err: $!"; my @lines = <$fh2>; print @lines[@line_numbers]; close $fh2;
我会这样做:
#!/bin/bash numbersfile=numbers datafile=data while read lineno < $numbersfile; do sed -n "${lineno}p" datafile done
我的方法不利的一面是,它会产生很多进程,所以它会比其他选项慢。 尽管它可读性更高。
sed -n -e "$(cat num |sed 's/$/p/')" file
其中num是文件的数字和文件是输入文件(测试OS / X雪豹)
$ cat num 1 3 5 $ cat file Line One Line Two Line Three Line Four Line Five $ sed -n -e "$(cat num |sed 's/$/p/')" file Line One Line Three Line Five
$猫的输入
一切
好
鸟
不
飞
$猫线
2
4
$ perl -ne'BEGIN {($ a,$ b)=`cat lines`}如果输入$。== $ a .. $。== $ $ b'
好
鸟
不
如果这对于一个班轮来说太多了,那就用
#! /usr/bin/perl use warnings; use strict; sub start_stop { my($path) = @_; open my $fh,$path or die "$0: open $path: $!"; local $/; return ($1,$2) if <$fh> =~ /s*(d+)s*(d+)/; die "$0: $path: Could not find start and stop line numbers"; } my($start,$stop) = start_stop "lines"; while (<>) { print if $. == $start .. $. == $stop; }
Perl的魔术开放允许创造性的可能性,如
$ ./lines-between'tac lines-between |'
打印如果$。 == $ start .. $。 == $ stop;
while(<>){
这是使用Tie :: File来做到这一点的一种方法:
#!/usr/bin/perl use strict; use warnings; use autodie; use Tie::File; @ARGV == 2 or die "Supply src_file and filter_file as argumentsn"; my ($src_file,$filter_file) = @ARGV; tie my @source,'Tie::File',$src_file,autochomp => 0 or die "Cannot tie source '$src_file': $!"; open my $filter_h,$filter_file; while ( my $to_print = <$filter_h> ) { print $source[$to_print - 1]; } close $filter_h; untie @source;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。