• ベストアンサー

ファイルを読み込んで改行だけの行を取り除きたい

こんばんは。 ファイルを読み込んで、改行だけの行を省いて、上書きしたいのですが なぜかうまくいきません。 ループ内にある改行の判定をするIF文がいけないと思うのですが…。 教えていただけないでしょうか? また、シングルクォーテーションダブルっクォーテーションは同じ意味 なのですか?「""」と「''」 作ったプログラムは以下です。 open(OUT,">$ssifile"); #改行のみのデータは除く @newtbl = (); foreach $siline ( @slines) { if ($slines ne "\n") { push @newtbl, $siline; } } print OUT @newtbl; close(OUT); 宜しくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.1

if文のところだけ、変数の名前が違うのが原因では? 他では $siline となっているのに、ここだけ $slines ですが・・・ クォートの違いについてですが、文字列を生成するという点では違いはありません。 ただ、文字列中に書かれた変数が、ダブルでは展開されるのに対し、シングルでは展開されません。 また、エスケープ文字も、シングルの方では \' と \\ 以外は無効になります。 例えば、$a = 123; の時、   print "$a\'\\\nXYZ"; では 123'\ XYZ と表示されるのに対し、   print '$a\'\\\nXYZ'; では $a'\\nXYZ と表示されます。 # CGI=Perl ではないので、この手の質問は Perl でしましょう。

その他の回答 (1)

  • tfp
  • ベストアンサー率37% (3/8)
回答No.2

まず、ダブルクォートとシングルクォートについては、leaz024さんの回答通り、変数展開されるかされないかの違いと、エスケープシーケンス処理(\nなどが展開)されるかされないかの違いがあります。同じだと思いこんでるといつか痛い目に遭います。変数展開が必要な物はダブルクォートで、必要ない物はシングルクォートで囲むよう癖をつけておくといいでしょう。 また、ダブルクォートやシングルクォート以外に好きな記号を使うこともできます。 下記はダブルクォート""と同じ、変数$textの中身が表示される print qq{$text}, qq#$text#, qq%$text%, qq|$text|; 下記はシングルクォート''と同じ、$textという文字列が表示される print q{$text}, q!$text!, q($text), q?$text?; 記号の前にqqをつけるとダブルクォートと同じ、qだとシングルクォートと同じです。 ただし、() [] {} など、かっことして意味のある記号を使う場合、対応するかっこを使う必要があります。また、記号自身を含む場合\でエスケープしてやるのは同じです。 これは使いこなすと便利です。 例えば <img src="$file.gif" alt="a"> という文字列を変数展開ありで、処理したいとします。 ダブルクォートを使うと、 print "<img src=\"$file.gif\" alt=\"a\">"; と、中の"の前に\を付けて全部エスケープしてやらないといけなくて面倒です。一個でもエスケープを忘れると構文エラーになります。 好きな記号を使えることを知っておけば、 print qq|<img src="$file.gif" alt="a">|; と、スマートに安全に書けます。 で、本題のファイル処理ですが、いろいろ方法はありますが、私が好んで使うのは、下記のような一時ファイルに出力し、renameで上書きするものです。 ------------------------------------------------------------------------ my $file = 'test.txt'; # ファイル名 open(IN, "$file") or die $!; # 読み取り用で開く open(OUT, ">$file.tmp") or die $!; # 一時ファイルを出力用に開く while (<IN>) { # 1行ずつ処理する next if /^\n*$/; # 改行だけの行は無視 print OUT $_; # 一時ファイルに出力 } close(IN); close(OUT); rename("$file.tmp", $file) or die $!; # 一時ファイルを元ファイルにリネーム(上書き) ------------------------------------------------------------------------ 上記はファイルが大きいときでも1行分しかメモリを消費しないで済みます。 @lines = <IN>; などと、全行読み込んでから処理すると、極端な話、1GBのファイルなら1GBメモリが消費されます。さらに別の配列にコピーなどしてたら2GB。