- ベストアンサー
特定の改行コードだけ削除する
CSVファイルを変換するPGを書きたいのですが、 変換したいCSVには改行コード\nと\r\nが混在しています。 改行コード\r\nはそのままにして \nだけ削除したいのですが どのように書けばよろしいのでしょうか。 Perlは5.12.2です。 よろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
0x0d→0x0d 0x0d0x0a→0x0d0x0a 0x0a→削除 なら binmode STDIN; binmode STDOUT; while(<STDIN>){ if ( /\r\n$/ ){ } elsif ( /\n$/ ){ chomp; } print $_; } として「foo.pl」 perl foo.pl < 入力ファイル > 出力ファイル
その他の回答 (5)
- nora1962
- ベストアンサー率60% (431/717)
#5です。 念のため \rは\x0d \nは\x0a にしておいてください。
お礼
お陰様で達成できました。 どちらの場合でも正常に動作しました。 ありがとうございます。
- N60-BASIC
- ベストアンサー率80% (17/21)
まず改行文字の表現について誤解されている部分があると思いますので説明しますが、 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として読み込む」といったことも可能です。 ただし、今回の例では入力する改行コードが混在しているため利用できません。
お礼
大変詳しく教えて頂きありがとうございました。 改行コードひとつとっても非常に奥が深いのですね。 やってみたところ目的の達成には至らなかったのですが、 教えていただきましたサイトを見た感じでは 出来ないとおかしいはずです・・・。 おそらく置換処理?以外のところで変なことをしてしまっているのだと思います。 なんとかこの方法でも実現出来るよう努力してみます(`・ω・´) ありがとうございました!
- Tacosan
- ベストアンサー率23% (3656/15482)
システムに依存する可能性はありますが, 手元の Windows7 で試した限りでは「ファイル全体をまとめて読込まないとダメ」かもしれません. $/ = undef; while (<>) { s/(?:[^\r]|^)\K\n//g; print; } とやって aaa abcde^M xyxxy^M bsrufhw というファイル (^M は \r, 行末に全て \n 付き) を処理すると aaaabcde xyxxy bsrufhw になります... あぁ, 出力の方もそれなりに何か指定しないとダメかも.
お礼
ご回答ありがとうございます。 試してみましたが、出力の仕方がうまく掴めず 折角のご回答を役立てることができませんでした。 もっと勉強して皆様それぞれの方法で目的達成出来るよう 努力致します。 ありがとうございました。
- kuzumiHK
- ベストアンサー率72% (132/183)
改行の混在を再現できていないので、 動作確認はできていませんが、 $hoge =~ s/([^\r]+|^)\n/$1/g; こんな感じでいかがでしょうか。 \nの前に\rがないか\nの前は行頭の場合、\nだけ削除
お礼
改めまして、ご回答ありがとうございました。 お陰様で大変勉強になりました。
補足
ご回答ありがとうございます。 しかし、すべての改行がはずれてしまいました。 もしかして$hogeには1行ずつでなく、csvファイル全体を放り込む必要があるのでしょうか? 違ってたら申し訳ありません。
- SAYKA
- ベストアンサー率34% (944/2776)
([^\r]+)\n とか・・・
お礼
改めましてご回答ありがとうございました。 素早いご回答、感謝しております。
補足
ご回答ありがとうございます。 不勉強で([^\r]+)\nをどう役立てていいかわかりませんでした。 kuzumiHK様のご回答と併せて試してみましたが、 やり方が不味いのかすべての改行コードがはずれてしまいました。 折角のご回答を活かせず申し訳ありません。
お礼
無事目的が達成できました。 ありがとうございます。 このスクリプトが何を意味するのか 調べてみてもよくわからなかったので、 理解できるまで研究してみます。 ありがとうございました!