也许我对于perl / awk / sed来说太老了,还太年轻而无法停止编程。这是我需要解决的问题:
我在TXT文件中有这样的信息:
Name:
Name 1
Phone:
1111111
Email:
some@email1
DoentMatterInfo1:
whatever1
=
Name:
Name 2
Phone:
22222222
DoentMatterInfo2:
whatever2
Email:
some@email2
=
Name:
Name 3
DoentMatterInfo3:
whatever2
Email:
some@email3
=
请注意,所需信息在下一行中,有一个记录分隔符(=),非常重要,有些记录并没有全部信息,但可能有我们不想要的信息。
因此,挑战在于如何在输出中提取所需的信息(如果存在):
Name 1 ; 111111 ; some@email1
Name 2 ; 222222 ; some@email2
Name 3 ; ; some@email3
我尝试过的方法虽然有点奏效,但仍然不是我想要的。
1.使用PERL
使用Perl,我得到了重要的字段:
while (<>) {
if ($_ =~ /Name/) {
print "=\n". scalar <>;
}
if ($_ =~ /Email/) {
print "; ". scalar <>;
}
if ($_ =~ /Phone/) {
print "; ". scalar <>;
}
}
我有一个类似的文件:
Name 1
; 1111111
; some@email1
=
Name 2
; 22222222
; some@email2
=
Name:
Name 3
; some@email3
=
现在使用sed将每条记录放在一行中:
SED使用SED,此命令替换换行,将信息放在一行中:sed ':a;N;$!ba;s/\n//g' input.txt > out1.txt
然后返回换行符:
sed 's/|=|/\n/g' out1.txt > out2.txt
所以我得到了一个文件,每行都有信息:
Name 1 ; 1111111 ; some@email1
Name 2 ; 22222222 ; some@email2
Name 3 ; some@email3
仍然不是我想从编码中得到的东西。我想要更好的东西,例如能够为丢失的电话填充空间,因此第二列可以始终是phone列。你明白了吗?
如您所见,不管使用的是Perl,AWk还是SED,寻找解决方案的目的都在于。我正在尝试Perl哈希...
提前致谢!!
这是一个Perl解决方案,需要并尝试
use warnings;
use strict;
use feature 'say';
my @fields = qw(Name Phone Email); # fields to process
my $re_fields = join '|', map { quotemeta } @fields;
my %record;
while (<>) {
if (/^\s*($re_fields):/) {
chomp($record{$1} = <>);
}
elsif (/^\s*=/) {
say join ';', map { $record{$_} // '' } @fields;
%record = ();
}
}
输入准备在数组中@fields
;这是唯一列出这些名称的地方,因此,如果需要在处理中添加更多字段,只需在此处添加即可。在中,还准备了用于匹配这些字段中任何一个的正则表达式模式$re_fields
。
然后,我们使用<>
operator逐行读取在命令行上提交的所有文件。
该if
条件捕获期望的关键字(如果存在)。在主体中,我们读取下一行的值并将其存储为键,该键即为捕获的关键字(不必知道哪个)。
在从=
记录开始的一行中打印(正确显示给定的样本文件)。我没有为缺少的字段(没有空格)和周围没有多余的空格放任何东西;
。根据需要调整输出格式。
为了完整地收集记录并在以后进行进一步处理(或仅打印),请将它们添加到合适的数据结构中,而不是打印。选择哪种存储取决于预想的处理类型。最简单的方法是将每个输出记录的字符串添加到数组中
my (@records, %record);
while (<>) {
...
elsif (/^\s*=/) {
push @records, join ';', map { $record{$_} // '' } @fields;
%record = ();
}
}
现在@records
已为所有记录准备好了字符串,可以将其打印为
say for @records;
但是,如果需要更多的处理,则最好将数组副本存储%record
为哈希引用,以便以后可以更轻松地操作各个组件。
my (@records, %record);
while (<>) {
...
elsif (/^\s*=/) {
# Add a key to the hash for any fields that are missing
$record{$_} //= '' for @fields;
push @records, { %record };
%record = ();
}
}
我为可能缺少的字段添加了一个键,以便哈希引用具有所有期望的键,并为其分配一个空字符串。另一种选择是分配undef
。
现在,您可以按以下方式访问每个记录中的各个字段:
foreach my $rec (@records) {
foreach my $fld (sort keys %$rec) {
say "$fld -> $rec->{$fld}"
}
}
或当然只使用Data::Dumper
诸如此类打印整个内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句