• 締切済み

改行コードが勝手に

はじめまして。perl初心者です。 見よう見まねでやりはじめたのですが。どうしてもわからないことがあります。 数十行ぐらいのテキストファイルがあるのですが、その中を訂正するcgiを作成しています。 htmlからそのファイル名を指定して、 open (DATA, "$file1"); #$file1がファイル名 として htmlのテキストエリアに表示して訂正し、それをさらに別のcgiで書き込むようにしています。 print "<form ACTION=\"hensyuu.cgi\" METHOD=\"POST\">\n; print "<textarea name=\"MSG\" cols=100 rows=30>\n"; foreach $gyou ( < DATA > ) { print $gyou; } print "</textarea>\n"; print "<input type=\"submit\" value=\"書込\">\n"; print "</form>\n"; hensyuu.cgiは open ( DATA,">>$file1" ); #ここでtextareaの内容を読み込み print DATA "$in{MSG}"; close ( DATA ); 編集したデータを見ると、各行ごとになぜか空白行が入ってしまいます。 バイナリエディタで見ると通常の0D0Aの前に0Dが追加され、0D0D0Aとなっているために そうなっていると思われます。 これってそういうものなのでしょうか。 それとも根本的にこんなやり方は間違っているのでしょうか。 ご教授のほど、よろしくお願いします。

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

LFの処理系でCRLFのファイルをそのまま読み込み:CRLFのまま残る →LF改行のファイルだとして、CRLF改行に変換:もとのCRはそのまま、LFがCRLFに変換される →CRCRLF ということだと思われます。 で、CRLFが出てくるのでWindowsを使っていると思いますが ・CGIを実行しているのはどこ? ・出力ファイルはどこにできるの?WindowsPC上でなかったらどうやってコピーしてくるの? Windows → Linux等のunix系で動作しているhttpサーバーで CGIを実行 →ファイルをアップロード(このときはバイナリーモード) → サーバー上にファイルが作成 →ftpでPC へ(このときはテキストモード) ってなってませんか? 対処方の一つは、どこかでCRを取り除くことです。 foreach $gyou ( < DATA > ) { $gyou =~ s/\r//g; #←とか print $gyou; }

marusu_jp
質問者

お礼

回答ありがとうございます

  • asciiz
  • ベストアンサー率70% (6803/9674)
回答No.1

改行は論理的には「\n」ひとつなんですが、環境によって実際の文字コードが違ってきます。 Unix系→LF(0x0A) Windows系→CR,LF(0x0D,0x0A) Macintosh→CR(0x0D) プログラム単体で動くのでいいんだったら、 ・一行読み込み ・改行を削除(chop($line); ) ・文字列処理 ・改行付きで出力(print $line, "\n";) でいいんですが。 WebサーバはUnix系だけども、表示したブラウザはWindowsだったりMacだったりするので困るのです…。 ---- 私が過去に作ったスクリプトでは、こんな乱暴な処理をしてました。 $buffer に全行読み込み後、 $buffer =~ s/(%0D|%0A)/&/g; # CR / LF は全て「&」文字に置換 $buffer =~ s/&+/&/g; # 連続&をまとめる $buffer =~ tr/&/\n/; # &を1改行とする これでも良かったのは、扱うデータが特定のCSVファイルだったため、 ・「&」文字が出てこない(自分のデータファイルでは) ・空行は存在しない という条件があったからです。 「&」文字ではなく、「%01 」みたいな文字データに出てこない(漢字等であっても)文字(コード)に置換するのが良いかも知れません。 空行の問題が解決しませんが…。 ---- あるいはどうせ3パターンなので、$bufferに読み込み後、 $buffer =~ s/\r\r\n/\n/g; $buffer =~ s/\r\n/\n/g; $buffer =~ s/\r/\n/g; と流してしてしまってもいいのかも?

marusu_jp
質問者

お礼

回答ありがとうございます。 自己解決しました。 ご指摘いただいたとおり、各行を表示する前や その後のファイル書込み前に改行コードを削除してみましたが 変化ありませんでした。 ただそこで気づいたのが、ファイルの最後の改行だけは削除されています。 ということは、変数MSGが複数行のデータではなく 1行のデータとして認識されているのでは? と考えました。 そこでファイル書込み前に @kakikomi = split ( /\n/, $in{MSG} ); としてデータを改行コードで配列に変換し、 書込みのときに foreach $a = ( @kakikomi ) { chop ( $a ); print DATA "$a\n"; } としたところ、うまくいけました。 自己解決したとはいうものの、kmeeさん、asciizさんのご指摘がなければ 解決できなかったところです。 本当にありがとうございました。