2011-10-24 19 views
3

2011年10月24日のパターンで日付を取得し、これを10,24,2011に変換するPerlスクリプトをコーディングしようとしています。ハッシュ値を持つ配列要素を置換する

これを行うために、私は、月の名前をキーとし、月の位置を値として表す数値を持つハッシュを用意しました。

私は入力文字列を読んで、上記の形式から月名を抽出する正規表現を使用します。

この月の名前を、月としてキーに対応する値に置き換えます。

これまでに記述したスクリプトはありますが、それは私のためには機能しません。

@dates配列は、この形式のすべての要素を持っています - > 10月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には、月名をハッシュで定義されている対応する数値で置き換えた新しい書式設定された配列があります。

map関数は、配列の要素をオンザフライで変換するために使用されます。

空白が続く文字の列は

この2011年は$ 1で参照される、パターン、10月24日から月名を抽出するために使用する正規表現です。

私は$日間{$ 1}

+7

なぜ「DateTime」を使用しないのですか? – CanSpice

+1

「働いていない」とはどういう意味ですか?これは '$ pattern =〜s /(* *)\ s/$ days {$ 1};'の簡単な構文エラーのように見えます; - 3番目の '/'文字が欠けていますが、あなたが完全に動作する小さなスクリプトを提供する場合、フィードバックを与えてください。 (ちなみに、CanSpiceの提案は 'DateTime'を使うのが良いですが、_some_ dateモジュールがいくつかのLinuxディストリビューションでは簡単に利用可能で、_other_dateモジュールは他のモジュールでも簡単に利用できることがわかりました。 。) – sarnold

+0

'map'文を' s /../../ my @output = @dates;と書くことを考えてください。 –

答えて

4

私はここにいくつかの問題を参照して、使用してハッシュに$ 1に対応する値を検索します。最初は、use strict;がないということです。

先頭のゼロの数字は、8進数形式(つまり、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 = ... 

あなたの置換の最後のスラッシュが欠落している、あなたは、おそらくそこにカンマを一致させたいですご希望の出力フォーマット、および.*はあなたが必要以上にまで食べるようになる:

returためにあなたの mapニーズに
$pattern =~ s/(\S*)\s/$days{$1}, /; 

ブロックn値を@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と関連パッケージを見てみたいかもしれません。

+0

詳細な説明はありがたいです。ええ、私はいつも私のプログラムを使って宣言されたstrictと変数を使ってプログラムを作成します。ここでは、ロジックを確認するスニペットをペーストするだけでした。あなたは非常にきれいな解決策を与えてくれました。 +1 –

1

非コンパイルコード(sarnoldが言ったように "/"を忘れてしまった)を貼り付けたことを除いて、あなたの正規表現は間違っています。

GREEDY正規表現を使用しました:.* - 可能な限り多くの文字を一致させることを意味します。だからOctoberの代わりにあなたの正規表現はOctober 24,になりました。あなたは\S+\s

+0

ありがとうございます、はい、REGEXは貪欲ですが、私は回避策が不明でした。 –

+0

このようなワイドマッチを使用しないでください(言い換えれば、私の答え - "\"を "\ S"に変更する)か、あるいは貪欲でない正規表現を使用してください。 "perldoc perlre"はあなたの友人です。 – DVK

0

を行う必要があり

あなたは「ハッシュ値を持つ代替配列要素、」したいですか、あなたは数字に月名をマッピングしたいです。それは後者だ場合は、次のことが少ないコードでmonth_name day yearmonth_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" 
+0

20分足らずで、私は4つ以上の回避策を詳細な解決策で得ました。ありがとう、あなたたちは速いです! :)私はこれらの機能についてもっと学びます。 –

+0

@NeonFlash:np :) – MisterEd

0

ここにあなたのコードにいくつかのフィードバックです:

  • があなたの貼り付けコードは非常にうまくコンパイルされません。
  • 厳密および警告は使用していません。
  • 01〜09は二重引用符で囲む必要があります。
  • ステートメント内に$_を再割り当てする必要はありません。
  • mapあなたが挿入しようとする値で終了する必要があり、例えば:map { s/(\w+)/$days{$1}/; $_ }
  • say for @outputが立派に見えます。 =)
+0

はい、これは単なるスニペットです。私はuse strictで完全なものを投稿せず、警告を使用し、myを使用して変数を宣言しませんでしたか?しかし、私がプログラムするとき、私はこれらの点を念頭に置いています:)また、私はその8進数のエラーを見つけ出し、修正しました。フィードバックありがとう:) –

+0

@NeonFlashようこそ。 – TLP

+0

@TLP - 'say'は古いPerlのバージョンでは使用できません。 OPは彼のことを示さなかった。 'map'の中に' $ _'を再割り当てすることはもちろん必須ではありませんが、読みやすさのために値が複数回使用されるならば一般的にはGood Practiceです。残りは大きなポイントです。 – DVK

関連する問題