Я пытаюсь с помощью одной строки записать строки, считанные из входного источника, в разные файлы в соответствии с содержимым поля самой строки.
Мой метод состоял в том, чтобы использовать хеш для хранения файловых дескрипторов, чтобы избежать многократного открытия одного и того же файла, добавляя ключи к этому хешу динамически, как только значение для поля, которое не появилось ранее, было найдено в новой строке для чтения .
Однако, используя значение хеша, которое хранит файловый дескриптор с общим вызовом 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, просто чтобы проверить, не была ли недавно исправлена какая-то ошибка.
Может быть, я упускаю что-то очевидное, но я не вижу, что.
У кого-нибудь есть идея?
Заранее спасибо.