Заменить элементы массива хэш-значениями - PullRequest
3 голосов
/ 25 октября 2011

Я пытаюсь закодировать Perl Script, который возьмет дату в Pattern, 24 октября 2011 г. и преобразует ее в 10,24,2011.

Для этого я подготовил Hash, которыйбудет иметь название месяца в качестве ключа и числовое значение, представляющее позицию месяца в качестве значения.

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

Замените название этого месяца значением, которое соответствует месяцу в качестве ключа.

Вот код, который я кодировал до сих пор, но он не работает для меня.

@ массив дат будет иметькаждый элемент в этом формате -> 24 октября 2011 года.

%days=("January",01,"February",02,"March",03,"April",04,"May",05,"June",06,"July",07,"August",08,"September",09,"October",10,"November",11,"December",12);

@output = map{
$pattern=$_;
$pattern =~ s/(.*)\s/$days{$1};
} @dates;

foreach $output (@output)
{
print $output."\n";
}

Вот небольшое объяснение того, что я пытаюсь сделать с этим кодом.

@ output будет иметь новый форматированный массивс именем месяца, замененным соответствующим числовым значением, представляющим его, как определено в хэш-функции.

функция карты используется для преобразования элементов массива на лету.

последовательностьe символов, за которыми следует пробел, является регулярным выражением, используемым для извлечения названия месяца из шаблона, 24 октября 2011 года.

На него будет ссылаться $ 1.

Я ищу соответствующее значение для$ 1 в хэше, $ days {$ 1}

Ответы [ 4 ]

4 голосов
/ 25 октября 2011

Я вижу здесь несколько проблем.Во-первых, use strict;.

Предполагается, что число с начальным нулем имеет восьмеричный формат (т. Е. Основание 8), поэтому 08 недопустимо.Вам нужен один из них:

%days = ("January",     1,  "February",     2,  ...
%days = ("January",   "01", "February",   "02", ...
%days = ("January" =>   1,  "February" =>   2,  ...
%days = ("January" => "01", "February" => "02", ...

Вы также должны объявлять свои переменные с помощью my:

my %days = ...
my @output = ...

Вы пропустили последний слеш при замене, возможно, вы хотитезапятая там, чтобы соответствовать желаемому выходному формату, и .* съест больше, чем вы хотите:

$pattern =~ s/(\S*)\s/$days{$1}, /;

Блок для вашего map должен вернуть значение, которое вы хотите в @outputно в настоящее время он возвращает 1 (см. perldoc perlop, чтобы узнать почему);что-то вроде этого будет вам лучше:

my @output = map {
    my $pattern=$_; # You don't need this, operating on $_ is fine here
    $pattern =~ s/(\S*)\s/$days{$1}, /;
    $pattern
} @dates;

Если вы действительно хотите убрать пробелы из вывода, то это должно сработать:

my @output = map {
    my $pattern=$_; # You don't need this, operating on $_ is fine here
    $pattern =~ s/(\S*)\s/$days{$1}, /;
    $pattern =~ s/\s//g;
    $pattern
} @dates;

Есть более компактные способысделайте это map, но я не хочу слишком сильно меняться и вводить вас в заблуждение.

И, как уже упоминалось в комментариях, вы можете избавить себя от некоторых неприятностей и взглянуть на DateTime и соответствующие пакеты.

1 голос
/ 25 октября 2011

Если оставить в стороне тот факт, что вы вставили некомпилируемый код (забыл обучить "/", как сказал Сарнольд), ваше регулярное выражение неверно.

Вы использовали регулярное выражение GREEDY: .* - то есть взять столькосимволы, насколько это возможно при сопоставлении.Таким образом, ваше регулярное выражение соответствует October 24, вместо October.

Нужно сделать \S+\s

0 голосов
/ 25 октября 2011

Вот некоторые отзывы о вашем коде:

  • Ваш вставленный код не очень хорошо компилируется.
  • Вы не использовали строгие и предупреждения.
  • 01значение 09 должно быть заключено в двойные кавычки.
  • Вам не нужно переназначать $_ в своем выражении map.
  • map должно заканчиваться значением, которое вы намереваетесь вставитьНапример: map { s/(\w+)/$days{$1}/; $_ }
  • say for @output выглядит лучше.=)
0 голосов
/ 25 октября 2011

Хотите ли вы «заменить элементы массива значениями хеша» или хотите сопоставить названия месяцев числам? Если это последнее, следующее преобразует month_name day year в month_number day year с меньшим кодом:

perl -le '$d=$ARGV[0]; for (qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}) { $i++; last if $d =~ s/\b$_[^\s]*/$i/i; }; print $d' "october 24, 2011"
...