こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

改行コードが勝手に

はじめまして。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となっているために
そうなっていると思われます。

これってそういうものなのでしょうか。
それとも根本的にこんなやり方は間違っているのでしょうか。

ご教授のほど、よろしくお願いします。

投稿日時 - 2011-06-09 23:02:21

QNo.6798370

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.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;
}

投稿日時 - 2011-06-09 23:40:07

お礼

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

投稿日時 - 2011-06-11 10:16:59

ANo.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;
と流してしてしまってもいいのかも?

投稿日時 - 2011-06-09 23:38:29

お礼

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

自己解決しました。


ご指摘いただいたとおり、各行を表示する前や
その後のファイル書込み前に改行コードを削除してみましたが
変化ありませんでした。
ただそこで気づいたのが、ファイルの最後の改行だけは削除されています。

ということは、変数MSGが複数行のデータではなく
1行のデータとして認識されているのでは?
と考えました。

そこでファイル書込み前に

@kakikomi = split ( /\n/, $in{MSG} );
としてデータを改行コードで配列に変換し、
書込みのときに

foreach $a = ( @kakikomi )
{
chop ( $a );
print DATA "$a\n";
}

としたところ、うまくいけました。

自己解決したとはいうものの、kmeeさん、asciizさんのご指摘がなければ
解決できなかったところです。

本当にありがとうございました。

投稿日時 - 2011-06-11 10:24:07

あなたにオススメの質問