2016-08-17 3 views
0

Я хочу (ab-) использовать глобальный% ENV для хранения хэша. Это выглядит по-разному для% ENV, чем для обычных хешей. в приведенной ниже программе $ENV{myhash} по-прежнему содержит 'myhash' => 'HASH(0x7ffad8807380)', а %ahash по-прежнему вокруг. возможно ли преобразовать гексаговый адрес обратно в точку в его местоположении вместо того, чтобы просто содержать строку? Наверное, я мог бы сериализовать и неэтериализовать хэш вместо этого. Каков правильный способ сделать это?perl сохранение хеша в% ENV

#!/usr/bin/perl -w 

use common::sense; 
use Data::Dumper; 

my %QENV = (nohash => 'noh'); 
my %ahash= (hv1 => 'htext1', hv2 => 'htext2'); 
$QENV{'myhash'} = \%ahash; 
print "works: ". Dumper(\%QENV)."\n\n\n"; 


$ENV{'myhash'} = \%ahash; 
print "fails: ". Dumper(\%ENV)."\n"; 
+3

no. переменные системной среды не имеют ничего общего с perl. вы не можете хранить perl-структуры данных в них. Вы должны сериализоваться в обычный текст, а затем сохраните этот сериализованный текст в var. –

+2

Какова причина этого желания? – stevieb

+0

- удобный способ передать глобальную переменную вокруг многих разных модулей и т. Д., Например, если я храню хэш http-сессии в% ENV в одном модуле, теперь любой другой perl-модуль или подпрограмма может проверить, существует ли сеанс http. просто выполнение только что определенного ($ ENV {'myhash'} и ... ', делающего разные вещи в зависимости от того, есть у нас это или нет. Я знаю, что трюк 'no strict vars' имеет смысл или нет? , на размышлениях, может быть, и нет. Я думал, что% ENV не наследует обратно к самому процессу. –

ответ

5

%ENV - магический хэш. Он отражает среду процесса. Чтение с него читается из среды, и запись на него изменяет среду.

Если вы можете гарантировать, что ссылочная переменная все еще жива (тем не менее, она по-прежнему находится в области видимости или с увеличением ее REFCNT), вы действительно можете создать ссылку на нее с адреса.

use strict; 
use warnings; 

use Data::Dumper; 

use Inline C => <<'__EOS__'; 

    SV* _newRV(IV iv) { 
     return newRV((SV*)iv); 
    } 

__EOS__ 

my %hash = (a => 1, b => 2); 
my $ref = \%hash; 
my $ref_string = "$ref"; 
my $addr = hex(($ref_string =~ /\((.*)\)/)[0]); 
my $ref2 = _newRV($addr); 
print(Dumper($ref2)); 

Я понятия не имею, почему вы хотите это сделать. Это не позволит другому процессу получить доступ к данным, поскольку один процесс не может получить доступ к памяти другого.

+0

darn (при поддержке резервного копирования). Я думал, что это был аккуратный трюк, чтобы было легко вводить глобальную переменную. , да, прежде чем кто-либо будет жаловаться на глобалы, это может быть полезно. 'use 5.018 'использует глобальный. В этом отношении то же самое можно сказать о% ENV. Это глобальный. Я предполагаю, что это будет не строго vars вместо этого с новым хешем, который не распространяется обратно. Это был также полезный трюк для изучения. спасибо. –

+1

wut /// Не знаю, что вы имеете в виду путем «распространения». Вы говорите, что он не может использоваться для передачи информации от ребенка к родительскому? Правда. Его нельзя даже использовать для передачи информации от родителя к дочерней. /// На самом деле 'use 5.018' имеет лексическую область, а не глобальную. /// Что такое анти-анти-глобальное разглашение? Никто не сказал, что вы не можете использовать глобальные переменные. Очень редко есть причина, но не всегда. Они могут быть объявлены с использованием 'our' вместо' my'. /// Не зная, что число является адресом, или использование 'newRV' для создания ссылки - это трюки. – ikegami

+0

Может быть, сериализовать структуру данных как JSON и получить ее. Но это немного хакерский вид IPC. – Sobrique

1

Возможно, вы хотите поделиться данными. Вот пример, который я часто там рассказывал, который показывает, как хранить данные в файле JSON, а затем извлекать его. JSON является перекрестным, поэтому данные могут использоваться многими языками программирования, а не только Perl. Хотя этот пример находится в рамках одного сценария, представьте, что это два разных приложения Perl:

use warnings; 
use strict; 

use JSON; 

my $file = 'data.json'; 

my %h = (
    foo => 'bar', 
    raz => { 
     ABC => 123, 
     XYZ => [4, 5, 6], 
    } 
); 

my $json = encode_json \%h; 

# write the JSON to a file, and close it 

open my $fh, '>', $file or die $!; 
print $fh $json; 
close $fh or die $!; 

# open the JSON file, and read it 

open my $json_file, '<', $file or die $!; 

my $read_json; 

{ 
    local $/; 
    $read_json = <$json_file>; 
} 

my $perl_hash = decode_json $read_json; 
Смежные вопросы