我正在逐行解析Perl中的一个大文件(以\ n结尾),但当我到达某个关键字时,说“TARGET”,我需要抓住TARGET和下一个完全关联的所有行空行。
所以,给定文件的一部分:
第1行
第2行
3号线
第4行目标
5号线抓住这条线
6号线抓住这条线
\ n
它应该成为:
第4行目标
5号线抓住这条线
第6行抓住这一行
我遇到麻烦的原因是我已经逐行浏览了这个文件;如何在解析过程中途改变我划分的内容?
答案 0 :(得分:23)
你想要这样的东西:
my @grabbed;
while (<FILE>) {
if (/TARGET/) {
push @grabbed, $_;
while (<FILE>) {
last if /^$/;
push @grabbed, $_;
}
}
}
答案 1 :(得分:14)
range operator适用于此类任务:
$ cat try
#! /usr/bin/perl
while (<DATA>) {
print if /\btarget\b/i .. /^\s*$/
}
__DATA__
Line 1
Line 2
Line 3
Line 4 Target
Line 5 Grab this line
Line 6 Grab this line
Nope
Line 7 Target
Linu 8 Yep
Nope again
$ ./try
Line 4 Target
Line 5 Grab this line
Line 6 Grab this line
Line 7 Target
Linu 8 Yep
答案 2 :(得分:10)
简短回答:perl中的行分隔符为$/
,因此当您点击TARGET时,可以将$/
设置为"\n\n"
,读取下一个“行”,然后将其设置回到“\ n”...etvoilà!
现在更长的一个:如果你使用English
模块(它为Perl的所有魔术变量提供合理的名称,那么$/
被称为$RS
或$INPUT_RECORD_SEPARATOR
如果您使用IO::Handle
,则IO::Handle->input_record_separator( "\n\n")
将有效。
如果您将此作为更大代码的一部分,请不要忘记本地化(在适当的范围内使用local $/;
)或将$/
设置为原始代码价值"\n"
。
答案 3 :(得分:4)
从perlfaq6回答How can I pull out lines between two patterns that are themselves on different lines?
你可以使用Perl有点奇特的运算符(在perlop中记录):
perl -ne 'print if /START/ .. /END/' file1 file2 ...
如果你想要文字而不是线条,你可以使用
perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...
但是如果您想要嵌套出现START到END,那么您将遇到本节中有关匹配平衡文本的问题中描述的问题。
这是使用..的另一个例子:
while (<>) {
$in_header = 1 .. /^$/;
$in_body = /^$/ .. eof;
# now choose between them
} continue {
$. = 0 if eof; # fix $.
}
答案 4 :(得分:2)
while(<FILE>)
{
if (/target/i)
{
$buffer .= $_;
while(<FILE>)
{
$buffer .= $_;
last if /^\n$/;
}
}
}
答案 5 :(得分:1)
use strict;
use warnings;
my $inside = 0;
my $data = '';
while (<DATA>) {
$inside = 1 if /Target/;
last if /^$/ and $inside;
$data .= $_ if $inside;
}
print '[' . $data . ']';
__DATA__
Line 1
Line 2
Line 3
Line 4 Target
Line 5 Grab this line
Line 6 Grab this line
Next Line
编辑以按照下面的注释修复退出条件。
答案 6 :(得分:0)
如果您不介意丑陋的自动生成代码,并假设您只想要TARGET
和下一个空行之间的行,并希望删除所有其他行,则可以使用此输出命令:
s2p -ne '/TARGET/,/^$/p'
(是的,这是暗示这个问题通常在sed
中更容易解决。:-P)
答案 7 :(得分:0)
如果你只想要一个循环(修改Dave Hinton的代码):
my @grabbed;
my $grabbing = 0;
while (<FILE>) {
if (/TARGET/ ) {
$grabbing = 1;
} elsif( /^$/ ) {
$grabbing = 0;
}
if ($grabbing) {
push @grabbed, @_;
}
}
答案 8 :(得分:0)
String deli_time = shared_preference.getString("delivery_time", "");
List<String> timeList1 = Arrays.asList(deli_time.split(" "));
String time_value = timeList1.get(1).trim()+" "+timeList1.get(2).trim();
Date dateObj = sdf2.parse(time_value);
time_value = sdf1.format(dateObj);
Date dateObj1 = sdf3.parse(timeList1.get(0));
dayOfTheWeek = sdf.format(dateObj1);
String time = "";
time = ZainbowDatabase.getInstance(MyBasket.this).getTimeForDay(mall_id, t1_vendor_id, dayOfTheWeek, 2);
if(time.length() > 0 && !time.equalsIgnoreCase("")){
String time1, time2 = "";
if(time.contains(",")){
List<String> timeList = Arrays.asList(time.split(","));
time1 = timeList.get(0);
time2 = timeList.get(1);
}else
time1 = time;
boolean check_time = AppConstant.checkTime(time1, time2, time_value);