質問 |
||
| 質問者:trfnc223 | ファイルの書き込み2 | |
|---|---|---|
困り度:
|
またまた失礼します。 やりたいことは以下です。 1.ディレクトリを開く。 2.ファイル達を読み込み。 3.追記用のデータファイルを開く。 4.「2」にデータを追記 5.別のディレクトリに書き出し。 以上です。 4番がうまくいきません。 ためしに4の工程を抜かすと問題なく書き出されます。 4の工程でやりたいことは、 1.タブ区切りのテキストファイルを読み込み。 2.書き出し用に読み込んだ(追記したいファイル)<productのpath="[ココの値!]"を取得。 3.「2」番で取得した値と「1」番で取得した値を比較。 4.「3」がtrueの行を追記して書き出し。 以上。 要するになにがしたいかというと、 仮にタブ区切りテキストには10行分のデータがあるとします。 それぞれの行には3つ分の値が入っており、先頭にIDが付いています。 一番最初に読み込んだファイル(追記したいファイル)にも同様にIDが振られており(<product path="ココ")そのIDとタブ区切りテキストのIDが一致した行だけ追記したいということです。 下記のコードだとなぜか、 10行分のデータがすべて追記されてしまいます。 コードは以下です。 #!/usr/bin/perl #既存ファイル読み込み&追記 $n_dir = "newXml/"; $b_dir = "xml/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $bfile="$b_dir$file"; $nfile="$n_dir$file"; $dfile="data/data.txt"; if (-T $bfile) { open(IN, $bfile);#既存ファイルオープン @list = <IN>; close(IN); open(OUT,">$nfile");#書き出しファイルオープン foreach $line (@list) { if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } if ($line =~ /\<\/product\>/) { open(IN, $dfile);#追加データファイルオープン while($data = <IN>){ chomp(@data = split(/\t/,$data)); $data[0] =~ s/\//_/g; if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 print OUT <<EOF; <ds path="$data[0]">$data[1]</ds> <kw>$data[2]</kw> $line EOF } else{next;} } close(IN) }else{print OUT $line;} } close(OUT); } else{next;} } closedir(DIR); 長々と申し訳ありません。 エラーなどは特にありません。 ご協力お願いします。 |
|
質問投稿日時:08/03/11 18:43 質問番号:3853704 |
||
回答良回答10pt |
|
| 回答者:sakusaker7 | たぶん if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } ここで$1に何か入っていると思っていて、さらに if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 ここでそれを参照しているつもりなんだろうけど、それじゃだめです。 まず$1とか$2とかで取り出すには、 $line =~ /path=(".*")/; のように、キャプチャのためのカッコを書かないといけません。 つぎに、仮にここでキャプチャしていたとしても if ($line =~ /\<\/product\>/) { こことか $data[0] =~ s/\//_/g; ここで正規表現を使った操作をしてしまっているから、ぶっ壊されます。 $<*digits*> Contains the subpattern from the corresponding set of capturing parentheses from the last pattern match, not counting patterns matched in nested blocks that have been exited already. (Mnemonic: like \digits.) These variables are all read-only and dynamically scoped to the current BLOCK. データファイルの読み込みは一回だけやれば十分だと思うけど もう寝るので指摘だけ :) |
|---|---|
| 種類:回答 どんな人:経験者 自信:参考意見 |
|
| |
回答日時:08/03/12 02:33 回答番号:No.3 |
|
| この回答へのお礼 | できました!!!! $line =~ /path="(.[^\"]*)"/;#path取得 $id = $1; 〜〜略〜〜 if($data[0] eq $id){#取得したパスとdata.txtとってきた値を比較 こうしたらちゃんと比較されました! ありがとうございます! |
回答良回答20pt |
|
| 回答者:menu_selec | またまた失礼。。 $data[0] と $1 の中身が空でないかチェックしても駄目ですか? if($data[0] ne ""){〜 >if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 の==をeqに変えてみても駄目ですか? (==は、数値でない場合や文字列として認識されてしまった数字の場合、正しく比較できないことがあります。 経験上、eqなら間違いなく比較してくれます) ご質問の件とはまったく無関係ですが、 >open(IN, $dfile);#追加データファイルオープン から >close(IN); までの間に処理をたくさん行なうと、その隙に外部からファイルアクセスがあったときに、ファイルを破壊されることがあります。 あらかじめ書き出す変数や配列を用意しておき、openからcloseまでを最短にするようにした方が安全ですよ。 前回私が書いたスクリプトが見本です。(恥) |
|---|---|
| 種類:アドバイス どんな人:専門家 自信:参考意見 |
|
| |
回答日時:08/03/12 01:01 回答番号:No.2 |
|
| この回答へのお礼 | またまたありがとうございます!! 空のチェックをしたら$1に値が入ってなかったです。 ただ、=をeqに変えたらちゃんとでなくなりました! つまり$1に値が入っていないので当然falseなので、 値が出ないという正しい処理になりました。 あとは$1にデータさえ入れば・・・ >までの間に処理をたくさん行なうと、その隙に外部からファイルアクセスがあったときに、ファイルを破壊されることがあります。 わざわざご指摘ありがとうございます! とても参考になりました!!! |
回答 |
|
| 回答者:Ceren | > 4.「2」にデータを追記 > 4番がうまくいきません。 「追加データファイルオープン」のところで「>>」の指定がないので 期待通りに動かないのではないですか? |
|---|---|
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| |
回答日時:08/03/11 18:56 回答番号:No.1 |
|
| この回答への補足 | ご回答ありがとうございます。 追記モードにするということでしょうか。 試してみましたけど変わりありませんでした。 |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |