使用存储在哈希值中的文件句柄的语法错误
Syntax error using a filehandle stored in a hash value
我正在尝试使用单行代码,根据行本身字段的内容将从输入源读取的行写入不同的文件。
我的方法是使用散列来存储文件句柄以避免多次打开同一个文件,一旦在新的行读取。
但是使用存储文件句柄的散列值与普通 print/printf 调用,例如
print $hash{ $field_value } "String"
导致编译错误。
例如,将 $hash{ $field_value }
替换为 STDERR
会导致干净的编译。
下面是一个单行示例。
$ cat /tmp/input_file
mail1.sql:INSERT INTO
mail2.sql:INSERT INTO
mail3.sql:INSERT INTO
mail4.sql:INSERT INTO
mail6.sql:INSERT INTO
mail7.sql:INSERT INTO
mail8.sql:INSERT INTO
mail9.sql:INSERT INTO
maildev.sql:INSERT INTO
$ perl -C -nE '
m{^(?<server>mail[^.]+)\.sql:(?<string>INSERT INTO)};
exists $fd->{$+{server}} or open($fd->{$+{server}}, ">>", "/tmp/". $+{server}.".tmp.sql");
print sprintf(qq{server %s.domain.tld command %s;\n}, $+{server}, $+{string});
' /tmp/input_file
server mail1.domain.tld command INSERT INTO;
server mail2.domain.tld command INSERT INTO;
server mail3.domain.tld command INSERT INTO;
server mail4.domain.tld command INSERT INTO;
server mail6.domain.tld command INSERT INTO;
server mail7.domain.tld command INSERT INTO;
server mail8.domain.tld command INSERT INTO;
server mail9.domain.tld command INSERT INTO;
server maildev.domain.tld command INSERT INTO;
# The files were opened, creating them. print-ing to STDOUT works fine.
$ ls -1 /tmp/mail*sql
/tmp/mail1.tmp.sql
/tmp/mail2.tmp.sql
/tmp/mail3.tmp.sql
/tmp/mail4.tmp.sql
/tmp/mail6.tmp.sql
/tmp/mail7.tmp.sql
/tmp/mail8.tmp.sql
/tmp/mail9.tmp.sql
/tmp/maildev.tmp.sql
# Now using $fd->{$+{server}} as filehandle for print
$ perl -C -nE '
m{^(?<server>mail[^.]+)\.sql:(?<string>INSERT INTO)};
exists $fd->{$+{server}} or open($fd->{$+{server}}, ">>", "/tmp/". $+{server}.".tmp.sql");
print $fd->{$+{server}} sprintf(qq{server %s.domain.tld command %s;\n}, $+{server}, $+{string});
' /tmp/input_file
syntax error at -e line 4, near "} sprintf"
syntax error at -e line 5, near ";}"
Execution of -e aborted due to compilation errors.
# Simplifying further
$ perl -C -nE '
my $a = "test";
exists $fd->{$a} or open($fd->{$a}, ">>", "/tmp/". $a.".tmp.sql");
print $fd->{$a} sprintf(qq{AAA %s AAA\n}, $a);
' /tmp/input_file
syntax error at -e line 4, near "} sprintf"
BEGIN not safe after errors--compilation aborted at -e line 4.
我已经尝试使用 perl 5.22 和 5.30 进行此操作,只是为了检查它是否是最近修复的某种错误。
也许我遗漏了一些明显的东西,但我看不到什么。
有人知道吗?
提前致谢。
您需要将手柄包裹在一个裸块中。
print { $hash{ $field_value } } "String";
这在 print
perldoc 中有记录。
If you're storing handles in an array or hash, or in general whenever
you're using any expression more complex than a bareword handle or a
plain, unsubscripted scalar variable to retrieve it, you will have to
use a block returning the filehandle value instead, in which case the
LIST may not be omitted:
print { $files[$i] } "stuff\n";
print { $OK ? *STDOUT : *STDERR } "stuff\n";
我正在尝试使用单行代码,根据行本身字段的内容将从输入源读取的行写入不同的文件。
我的方法是使用散列来存储文件句柄以避免多次打开同一个文件,一旦在新的行读取。
但是使用存储文件句柄的散列值与普通 print/printf 调用,例如
print $hash{ $field_value } "String"
导致编译错误。
例如,将 $hash{ $field_value }
替换为 STDERR
会导致干净的编译。
下面是一个单行示例。
$ cat /tmp/input_file
mail1.sql:INSERT INTO
mail2.sql:INSERT INTO
mail3.sql:INSERT INTO
mail4.sql:INSERT INTO
mail6.sql:INSERT INTO
mail7.sql:INSERT INTO
mail8.sql:INSERT INTO
mail9.sql:INSERT INTO
maildev.sql:INSERT INTO
$ perl -C -nE '
m{^(?<server>mail[^.]+)\.sql:(?<string>INSERT INTO)};
exists $fd->{$+{server}} or open($fd->{$+{server}}, ">>", "/tmp/". $+{server}.".tmp.sql");
print sprintf(qq{server %s.domain.tld command %s;\n}, $+{server}, $+{string});
' /tmp/input_file
server mail1.domain.tld command INSERT INTO;
server mail2.domain.tld command INSERT INTO;
server mail3.domain.tld command INSERT INTO;
server mail4.domain.tld command INSERT INTO;
server mail6.domain.tld command INSERT INTO;
server mail7.domain.tld command INSERT INTO;
server mail8.domain.tld command INSERT INTO;
server mail9.domain.tld command INSERT INTO;
server maildev.domain.tld command INSERT INTO;
# The files were opened, creating them. print-ing to STDOUT works fine.
$ ls -1 /tmp/mail*sql
/tmp/mail1.tmp.sql
/tmp/mail2.tmp.sql
/tmp/mail3.tmp.sql
/tmp/mail4.tmp.sql
/tmp/mail6.tmp.sql
/tmp/mail7.tmp.sql
/tmp/mail8.tmp.sql
/tmp/mail9.tmp.sql
/tmp/maildev.tmp.sql
# Now using $fd->{$+{server}} as filehandle for print
$ perl -C -nE '
m{^(?<server>mail[^.]+)\.sql:(?<string>INSERT INTO)};
exists $fd->{$+{server}} or open($fd->{$+{server}}, ">>", "/tmp/". $+{server}.".tmp.sql");
print $fd->{$+{server}} sprintf(qq{server %s.domain.tld command %s;\n}, $+{server}, $+{string});
' /tmp/input_file
syntax error at -e line 4, near "} sprintf"
syntax error at -e line 5, near ";}"
Execution of -e aborted due to compilation errors.
# Simplifying further
$ perl -C -nE '
my $a = "test";
exists $fd->{$a} or open($fd->{$a}, ">>", "/tmp/". $a.".tmp.sql");
print $fd->{$a} sprintf(qq{AAA %s AAA\n}, $a);
' /tmp/input_file
syntax error at -e line 4, near "} sprintf"
BEGIN not safe after errors--compilation aborted at -e line 4.
我已经尝试使用 perl 5.22 和 5.30 进行此操作,只是为了检查它是否是最近修复的某种错误。
也许我遗漏了一些明显的东西,但我看不到什么。
有人知道吗?
提前致谢。
您需要将手柄包裹在一个裸块中。
print { $hash{ $field_value } } "String";
这在 print
perldoc 中有记录。
If you're storing handles in an array or hash, or in general whenever you're using any expression more complex than a bareword handle or a plain, unsubscripted scalar variable to retrieve it, you will have to use a block returning the filehandle value instead, in which case the LIST may not be omitted:
print { $files[$i] } "stuff\n"; print { $OK ? *STDOUT : *STDERR } "stuff\n";