プロが教える店舗&オフィスのセキュリティ対策術

CSVファイルを変換するPGを書きたいのですが、
変換したいCSVには改行コード\nと\r\nが混在しています。

改行コード\r\nはそのままにして
\nだけ削除したいのですが
どのように書けばよろしいのでしょうか。

Perlは5.12.2です。

よろしくお願いします。

A 回答 (6件)

0x0d→0x0d


0x0d0x0a→0x0d0x0a
0x0a→削除
なら
binmode STDIN;
binmode STDOUT;
while(<STDIN>){
if ( /\r\n$/ ){
}
elsif ( /\n$/ ){
chomp;
}
print $_;
}
として「foo.pl」
perl foo.pl < 入力ファイル > 出力ファイル
    • good
    • 0
この回答へのお礼

無事目的が達成できました。
ありがとうございます。

このスクリプトが何を意味するのか
調べてみてもよくわからなかったので、
理解できるまで研究してみます。
ありがとうございました!

お礼日時:2011/01/25 21:39

#5です。


念のため
\rは\x0d
\nは\x0a
にしておいてください。
    • good
    • 0
この回答へのお礼

お陰様で達成できました。

どちらの場合でも正常に動作しました。
ありがとうございます。

お礼日時:2011/01/25 21:40

まず改行文字の表現について誤解されている部分があると思いますので説明しますが、


C言語等での「\n」とPerlでの「\n」は意味や挙動が異なります。

おそらく質問者さんは「\r」をCR(\x0D)、「\n」をLF(\x0A)と勘違いされていると
思いますが、Perlの場合、「\n」は「(内部処理における論理的な)改行文字」という
意味であって、特定の文字コードを表す文字ではありません。
実際の動作では、入出力の時点で「\n」が表す文字コードはプラットフォームOSによって
異なります。

=Perlでの「\n」が示す文字コード=
UNIX系(Cygwin含む) ~ LF(\x0A)
Windows(ActivePerl) ~ CR+LF(\x0D\x0A)
Mac ~ CR(\x0D)

従って、質問者さんのPerl実行環境が上記のいずれかはわかりませんが
改行コードの文字種をプラットフォームに依存せず処理したい場合は、文字コードを直接記述する必要があります。

例として、OSプラットフォームの標準に合わせて改行コードを統一するには
以下のような処理が一般的です。(以下、$strが「改行を含む文字列」だとします)

$str =~ s/\x0D\x0A|\x0D|\x0A/\n/g; # CR+LF/CR/LFをすべて\nに統一する

# 大崎さんの「Perlメモ」がこのあたり詳しいです。
# http://www.din.or.jp/~ohzaki/perl.htm#CRLF_Unify

今回の質問の場合は、LF(\x0A)を置換ではなく削除したいという意図だと思いますので、
$str =~ s/\x0A//g; # LFを削除する
$str =~ s/\x0D/\x0D\x0A/g; # CRをCR+LFに置換する
でうまくいくのではないでしょうか。OSにも依存しないはずです。

(以下、ご参考まで)
もしOS標準とは異なる改行コードで入出力する必要がある場合、
Perl5.8以降であればPerlIOによる改行文字種の指定ができます。

my $str = "...\n...\n"; # 改行コードを含む文字列
open(my $fh, '>:lf', $filename) or die($!); # どんなOS上でも改行コードLFで出力するように指定
print $fh $str; # \nがLFとして出力される
close($fh);

ただし(出力の場合)改行をあらかじめ\nに統一しておく必要があります。
改行コードが混在していない前提であれば、ファイル入力においても
「WindowsでLFを\nとして読み込む」といったことも可能です。
ただし、今回の例では入力する改行コードが混在しているため利用できません。
    • good
    • 0
この回答へのお礼

大変詳しく教えて頂きありがとうございました。
改行コードひとつとっても非常に奥が深いのですね。

やってみたところ目的の達成には至らなかったのですが、
教えていただきましたサイトを見た感じでは
出来ないとおかしいはずです・・・。

おそらく置換処理?以外のところで変なことをしてしまっているのだと思います。
なんとかこの方法でも実現出来るよう努力してみます(`・ω・´)
ありがとうございました!

お礼日時:2011/01/25 21:46

システムに依存する可能性はありますが, 手元の Windows7 で試した限りでは「ファイル全体をまとめて読込まないとダメ」かもしれません.



$/ = undef;
while (<>) {
s/(?:[^\r]|^)\K\n//g;
print;
}
とやって
aaa
abcde^M
xyxxy^M
bsrufhw
というファイル (^M は \r, 行末に全て \n 付き) を処理すると
aaaabcde
xyxxy
bsrufhw
になります... あぁ, 出力の方もそれなりに何か指定しないとダメかも.
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
試してみましたが、出力の仕方がうまく掴めず
折角のご回答を役立てることができませんでした。

もっと勉強して皆様それぞれの方法で目的達成出来るよう
努力致します。
ありがとうございました。

お礼日時:2011/01/26 00:48

改行の混在を再現できていないので、


動作確認はできていませんが、

$hoge =~ s/([^\r]+|^)\n/$1/g;

こんな感じでいかがでしょうか。
\nの前に\rがないか\nの前は行頭の場合、\nだけ削除

この回答への補足

ご回答ありがとうございます。
しかし、すべての改行がはずれてしまいました。

もしかして$hogeには1行ずつでなく、csvファイル全体を放り込む必要があるのでしょうか?
違ってたら申し訳ありません。

補足日時:2011/01/23 15:47
    • good
    • 0
この回答へのお礼

改めまして、ご回答ありがとうございました。
お陰様で大変勉強になりました。

お礼日時:2011/01/26 00:49

([^\r]+)\n



とか・・・

この回答への補足

ご回答ありがとうございます。
不勉強で([^\r]+)\nをどう役立てていいかわかりませんでした。
kuzumiHK様のご回答と併せて試してみましたが、
やり方が不味いのかすべての改行コードがはずれてしまいました。
折角のご回答を活かせず申し訳ありません。

補足日時:2011/01/23 15:45
    • good
    • 0
この回答へのお礼

改めましてご回答ありがとうございました。
素早いご回答、感謝しております。

お礼日時:2011/01/26 00:51

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