在AWK中,对于在两个文件上运行的脚本,通常会看到这种结构:
awk 'NR==FNR { print "first file"; next } { print "second file" }' file1 file2
使用以下事实:定义了两个变量:FNR
,它是当前文件中的行号,NR
是全局计数(相当于Perl' s {{ 1}})。
在Perl中有类似的东西吗?我想我可以使用$.
和一个计数器变量:
eof
这有效,但感觉我可能会遗漏一些东西。
为了提供一些上下文,我写了this answer,其中我手动定义了一个哈希,但是,我想从第一个文件中的值填充哈希值,然后在第二个文件上进行替换。我怀疑在Perl中有一种巧妙的,惯用的方式。
答案 0 :(得分:2)
看起来你的目标是使用相同的循环来读取两个文件,并在循环内部选择如何处理数据。我会避免这个想法,因为你在同一段代码中隐藏了两个不同的进程,使得它不清楚发生了什么。
但是,在只有两个文件的情况下,您可以将当前文件与@ARGV
的第一个元素进行比较,就像这样
perl -nE 'if ($ARGV eq $ARGV[0]) { say "first file" } else { say "second file" }' file1 file2
忘记我热爱的单行程序,我只是明确地打开$ARGV[0]
和$ARGV[1]
。也许像这样命名它们
use strict;
use warnings;
use 5.010;
use autodie;
my ($definitions, $data) = @ARGV;
open my $fh, '<', $definitions;
while (<$fh>) {
# Build hash
}
open $fh, '<', $data;
while (<$fh>) {
# Process file
}
但是如果你想利用自动开放设施那么你可以像这样混淆@ARGV
use strict;
use warnings;
my ($definitions, $data) = @ARGV;
@ARGV = ($definitions);
while (<>) {
# Build hash
}
@ARGV = ($data);
while (<>) {
# Process file
}
答案 1 :(得分:2)
不幸的是,perl
没有类似的NR==FNR
构造来区分两个文件。你可以做的是使用BEGIN
块处理一个文件和主体来处理另一个。
例如,要使用以下内容处理文件:
<强>的map.txt 强>
a=apple
b=ball
c=cat
d=dog
<强> alpha.txt 强>
f
a
b
d
你可以这样做:
perl -lne'
BEGIN {
$x = pop;
%h = map { chomp; ($k,$v) = split /=/; $k => $v } <>;
@ARGV = $x
}
print join ":", $_, $h{$_} //= "Not Found"
' map.txt alpha.txt
f:Not Found
a:apple
b:ball
d:dog
<强>更新强>
我给出了一个非常简单的例子,现在当我看到它时,我只能说TIMTOWDI
,因为你能做到:
perl -F'=' -lane'
if (@F == 2) { $h{$F[0]} = $F[1]; next }
print join ":", $_, $h{$_} //= "Not Found"
' map.txt alpha.txt
f:Not Found
a:apple
b:ball
d:dog
但是,我可以肯定地说,NR==FNR
没有perl
构造,您可以根据文件以各种不同的方式处理它们。