변수의 값을 Perl 변수 이름으로 어떻게 사용할 수 있습니까? [복제하다
-
19-09-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
이 모든 어리석은 질문에 대해 죄송합니다. 저는 Perl 프로그래밍에 빠졌고 Perl 프로그래머처럼 생각하기가 정말 어렵다는 것을 알게되었습니다.
오늘의 바보 같은 질문 : 파이프 구분 파일을 ID 필드를 키로 사용하여 구분 된 파일을 해시에로드합니다.
#open file
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$id} = {
"path" => $path,
"date" => $date
};
}
그러나 실제로 경로가되기 위해 열쇠가 필요할 때 몇 번이나 그 이유는 어떤 이유로 든 ID가 독특하지 않기 때문에 내가 넣을 수있는 밝은 아이디어를 가지고 있었기 때문입니다. 그것은 모두 서브 루틴에 들어가서 변수의 이름을 전달하여 열쇠로 사용합니다.
load_hash("path");
sub load_hash {
my $key = shift;
#do stuff, and then in while loop
$hash{${$key}} = #and so on
}
그러나 perldb x $ {$ key}에서 x $ {path}는 값을 $ 경로로 인쇄하지만 항상 undef입니다.
내가 시도하는 일을하는 방법이 있습니까?
티아
해결책
이 같은?
use Carp 'confess';
sub load_hash {
my $key = shift;
# ...
while (...) {
# ...
my %line; # important that this is *inside* the loop
@line{qw (id path date)} = split /\|/;
confess "BUG: unknown key '$key'" unless exists $line{$key}; # error checking
$hash{$line{$key}} = \%line;
delete $line{$key}; # assuming you don't want the key value duplicated
}
}
다른 팁
"상징적 참조"를 사용하려고합니다. 문제가 있고 "이봐, 상징적 참조로 이것을 해결하겠습니다"라고 생각한다면 이제 두 가지 문제가 있습니다.
우선, 그들은 글로벌에서만 일합니다. 당신은 선언했습니다 $path
어휘 (선언 된 블록에서만 볼 수 있음)로서 Load_Path는 그것을 볼 수 없습니다. 아니, 만들지 마세요 $path
글로벌.
둘째, Symbolic Refs는 스파게티 코드를 만듭니다. 글로벌은 충분히 나쁘다. 그들은 언제 어디서나 어디서나 접근 할 수 있습니다. 글로벌에 대한 상징적 참조로 어떤 글로벌에 액세스할지 알 수 없습니다. 이것은 무엇을 변화시킬 수 있는지 추적하는 것이 불가능합니다. 이는 이유 strict
그들을 끌어냅니다. 켜다 strict
언제 끄야하는지 알 때까지 켜십시오.
나는 당신이 성취하려는 것을 완전히 확신하지 못하지만 이것이 괜찮은 것 같습니다.
my %hash;
while (<MY_FILE>) {
chomp;
my ($id, $path, $date) = split /\|/;
$hash{$path} = {
"path" => $path,
"date" => $date
};
}
그러나 나는 아마도 라인의 구문 분석을 함수로 옮기고 해시 할당을 기본 루프로 남겨 둡니다. 라인을 구문 분석하는 것은 명확한 논리 덩어리이며 라인을 파일 해시에 할당하는 것과 완전히 분리 될 수 있습니다. 좋은 징조는 그 것입니다 %hash
글로벌 일 필요는 없습니다.
my %hash;
while (<MY_FILE>) {
my $line = parse_line($_);
my $id = $line->{path};
$hash{$id} = $line;
}
my @fields = qw(id path date);
sub parse_line {
my $line = shift;
chomp $line;
my %data;
# This is assigning to a hash slice. Look it up, its handy.
@data{@fields} = split m{\|}, $line;
return \%data;
}