電子書籍の厳選無料作品が豊富!

たいへん困っています。Perlでプログラムを作成しており配列要素の削除を行なおうとしています。
例えば下のようなデーターをdata.txtファイルに保存しているとしてください。

1,洋服,婦人服,子供服,男性服,
2,時計,
3,アクセサリ,

上のデーターで1行目にある子供服を削除して
1,洋服,婦人服,男性服,
2,時計,
3,アクセサリ,
のようにずらしたいのです。

私がとった方法はデーターをopenで開きforeachで行をまず呼びこみます。
if(!open(DATA,"$data")){&error('ファイル読み取りエラー。'); }
else{
@data=<DATA>;
close(DATA);
}
foreach $line (@data){
chomp $line;
($no,@sub)=split(/,/,$line);
if($no eq 1){
$i=-1;
foreach (@sub){$i++;
if($sub[$i] eq '子供服'){next;}
else{push @newsub,"$sub[$i]";next; }
}
push @newline,"$no,@newsub\n";}
else{push @newcline,"$line\n";}
}
これで@newlineを表示すると
1,洋服,婦人服, 男性服,
2,時計,
3,アクセサリ,

のように男性の前の部分が半角空白として保存されます。

どうしてなのでしょうか?そもそもこういったやり方が間違っているのか、それとも一部だけまちがっているのかもわかりません。お手数ですがどなたか教えてください。

A 回答 (4件)

簡単なことを複雑にやっている印象があります。

本当は、bakusuiさんにとって良くないことだと思いますが、私だったら、こうするという例を示します。

$datfile = @ARGV[0];

open(DATA, $datfile) || die "can't open $datfile\n";
while($line = <DATA>){
($num, @items) = split(/,/, $line);
if($num == 1){
$line =~ s/子供服\s*,//g;
}
print $line;
}
    • good
    • 0

>1行をforeachで探し出してpushで振り分けるようにしていました。



残したいデータもしくは削除したいデータを振り分けて個別に後で処理したいのなら、そうすべきでしょう。単にファイルに書き分けるだけなら、配列に入れずに、そのままファイルに書き出せばよいのではないでしょうか。


>あと、$line =~ s/子供服\s*,//g; の\s*は必要なのでしょうか?

もちろん、なくても構いません。単にデータ中に余計なスペースがあった場合の予防です。自分で作成したデータと言えど信用しません(余計なスペースがどこに入っているか分からないですから)。
以下のように、まず最初に余分なスペースを消去した方がいいですね。

$line =~ s/[ \t]+//g; #余計なスペース、タブの消去
$line =~ s/子供服,//g;
    • good
    • 0
この回答へのお礼

ありがとうございました。本当に助かりました。
感謝致します。
勉強にもなりました。
失礼します。

お礼日時:2003/05/28 00:59

#1さんが言っておられる通り、複雑なことをやりすぎている気がします。

(文字列の置換で十分対応できる。)

どうしても、配列の要素から特定の条件に当てはまるものを削除したいというのであれば、grep等を使うのが一番スマートな気がします。
今の場合であれば、

@sub = grep { $_ ne '子供服' } @sub;

等は、いかがでしょうか?
    • good
    • 0

補足します。



> 簡単なことを複雑にやっている印象があります。

文字列のレベルで処理できることに対して、わざわざ配列を使っているという意味です。文字列のレベルで処理できることは、文字列の置換や消去で行った方が良いでしょう(プログラムが簡単)。
今回の質問の例では、わざわざ配列に入れ直す必要もないと思います。もちろん、処理内容(例えば、行内の項目をソートしたりする場合)によっては、配列に入れ直した方が良いでしょう。
    • good
    • 0
この回答へのお礼

結論からいいますと、うまくいきました。
感動しました。一度頭の中で配列を使うと思いこんでしまうとそればっかりしてました。
たいへん感謝いたします。
いままでの傾向(私自身的に)では例えば掲示板のかきこみなどを削除をするとき1行をforeachで探し出して
pushで振り分けるようにしていました。1行まるごと削除する場合はこれでいいのですよね?

文字列レベルの時おっしゃっていたようにすればいいんでしょうか?

あと、$line =~ s/子供服\s*,//g;
の\s*は必要なのでしょうか?
これを付加しなくてもうまくいってるような気がするのですが・・・\s\は0個以上空白文字ですよね?あったほうがいいのですか?

お礼日時:2003/05/27 15:12

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!