質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.82%

perlでファイルへprintした際の最終行

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,334

ransky

score 12

以下のようなコードでテキストファイルを出力させます。
自分が意図した処理はできているのですが、出力したoutput.txtを開くと、最終行に改行記号もない空の行(この表現が正しいのか不明ですが)があります。
下のコードの$Inputに使用しているENST_list.txtも別のperlコードで出力しているのですが、同じく最終行に空の行があり、手動でその行を消してからでないと下のコードがうまく動きません。

どのような方法で解決できるか、ご教授いただけると幸いです。

やりたいこと

1)perlのファイル出力で、下の例のような3行目が出ないようにしたい、または
2) 何らかの方法で3行目を削除したい

1行目;A\n
2行目;B\n
3行目;何もない行

試したこと

perlで空の行問題が解決できないので、出力した後に、
ファイルの最終行である空の行をsedで削除しようとしたのですが、sedで認識される最終行($)は、改行コードが存在している一番最後の行(実際にはその下に空の行がある)のようでした。
sedで消えるのは上の例だと2行目で、
1行目;A\n
2行目;何もない行
という結果になってしまいます。

コード

my $outfile = 'output.txt';
my $Input = 'ENST_list.txt'; #最終行に空の行があると1行目のマッチングが成立しなくなる
my $bed = 'hg19_Ensembl_gene.bed';
open(IN , $Input) or die "$!";

    while (my $In_line = <IN>) {
                chomp($In_line);
                @In_data = split(/\t/, $In_line);

                open(DATA, "+>> $outfile") or die "$!";
                open(BN, $bed) or die "$!"; 

            while(my $bed_line = <BN>){

                chomp($bed_line);
                @bed_data = split(/\t/, $bed_line);

                    if ("$In_data[0]" eq "$bed_data[3]" ){

                        print DATA "@bed_data\n";
                    }
                } 
                close BN;
                close DATA;
            }

                

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • showkit

    2019/04/24 10:03

    コードは 書き方を参考に コード行として記述することをお勧めします。
    プログラム以前に
    1行目;A\n
    2行目;B\n
    と書けば、当然 最後に空行が出力されますので 2行目: B と書くしかないですね。書いた後で末尾の 改行を消す手もあるかと思います。

    キャンセル

  • ransky

    2019/04/24 10:27

    ご回答ありがとうございます。
    コード行として記述しました、書き方がわかっていなくて申し訳ありませんでした。
    末尾の改行を消すということは、chompでしょうか、考えてみます。

    キャンセル

回答 5

checkベストアンサー

0

既にたどり着いているようですが、<> で入力を拾う時には改行を含めて入ってくるので、改行を除去したいのであれば chomp で処理する必要があります。

1行目;A\n
2行目;B\n
3行目;何もない行 

というのは正しい形式で、むしろ

1行目;A\n
2行目;B

の方が想定外のことが起きやすい印象はあります。

現在のコードには chomp が入っていますが、これでも動作していない状況なのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/24 16:35

    ssasaki様、KojiDoi様、ありがとうございます。
    提案していただいたものを試してみて結果を報告いたします。

    キャンセル

  • 2019/04/24 18:09

    ssasaki様、KojiDoi様、

    ENST_list.txtをVisual Studio Codeで開くとLFと表示されていたので、LFだと信じ込んでしまっていましたが、
    od -cで調べると、\r\nと\nが混ざっていました。
    別のファイル(ENST_original.txt)からperlコードでENST_list.txtを出力したのですが、ENST_original.txtの改行コードは全て\r\nになっていました。
    ENST_list.txtの改行コードをLFに統一することで、私の書いた最初のコードでも動きました。

    また、ENST_list.txtの改行コードに\r\nと\nが混ざった状態でも、
    s/\r\n/\n/;
    s/(\x0a|\x0d)*$//;
    は共に期待した出力ができました。

    さらに、if blockをKojiDoi様のコードに置き換えた場合
    1) ENST_list.txtの改行コードに\r\nと\nが混ざった状態
    In_data =697883844848484848525056484955
    bed_data=697883844848484848525056484955
    In_data =697883844848484848535053505453
    bed_data=697883844848484848535053505453

    2) ENST_list.txtの改行コードに\r\nと\nが混ざった状態で、最終行の改行記号をエディタで削除した場合
    In_data =697883844848484848525457525652
    bed_data=697883844848484848525457525652
    In_data =697883844848484848525056484955
    bed_data=697883844848484848525056484955
    In_data =697883844848484848535053505453
    bed_data=697883844848484848535053505453

    3) ENST_list.txtの改行をLFに修正した場合
    In_data =697883844848484848525457525652
    bed_data=697883844848484848525457525652
    In_data =697883844848484848525056484955
    bed_data=697883844848484848525056484955
    In_data =697883844848484848535053505453
    bed_data=697883844848484848535053505453

    となりました。私の現在の知識では
    s/(\x0a|\x0d)*$//; や if blockの書き換えで出力されたものの意味が理解できないので学習いたします。

    改行コード確認の重要性がわかりました。
    お二人のご助言に感謝いたします。
    ありがとうございました。

    キャンセル

  • 2019/04/25 10:39

    解決して良かったです。
    VSCode って勝手に改行コード変えちゃうのですね。知らなかったです(^_^;)

    キャンセル

0

1行目;A\n
2行目;B

という出力を行えばいいんじゃないでしょうか

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/24 14:18

    ご回答ありがとうございます。
    ご指摘のように、
    最後の行の前まで改行記号をつけて、最終行だけ改行記号をつけない。
    または
    最終行も含めて改行記号をつけて、あとで最終行だけ改行記号を削除するで良さそうですので、考えてみます。

    キャンセル

0

「改行の存在しない空の行」というのがどうもよく分からないのですが、とりあえず対症療法を考えてみました。

外側のループ@In_data = split(/\t/, $In_line);の直後に(defined $In_data[1]) or next;
と加えて、「分割すべきデータがないならループの実行をスキップする」ようにすれば空行の出力はなされないと思います。

しかしその前に「別のperlコード」がゴミを吐き出すのを修正しておかないと、あとあと何か作業するたびに同じ問題に手間取ることになると思いますよ。

あと、なぜループの中で出力ファイルのopenとcloseを繰り返しているのでしょうか? まあ動くけど、無駄じゃないですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/24 13:52

    ご回答ありがとうございます。
    openとcloseは位置を動かして書き直しても動きました。

    「空の行」が出るのは出力ファイルの最終行のみで、
    print DATA "@bed_data\n";としている以上は
    1行目;A\n
    2行目(文字のある最終行);B\n
    3行目(最終行);何もない行
    という形式で文字列出力されるのがprintの機能として正しいという理解でよいのでしょうか。

    キャンセル

0

perlのファイル入出力について詳しくないので間違っていたらすみませんが、

$ sed '$d'


では削除できないのですか?
つまり上記のコードの最後に下記の1行を足して実現できないのでしょうか?

`sed -i '\$d' $outfile`;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-1

決してスマートなやり方ではないし、とてもお勧めできませんが

#!/usr/local/bin/perl

open(IN, "< in.txt");
my @read = <IN>;
close(IN);

pop(@read);

open(OUT, "> out.txt");
print(OUT @read);
close(OUT);


で、お望みの動きになります(自分の環境で動作確認)。
perl のシェバンやファイル名は適宜、置き換えてください。
 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/24 15:05

    どう考えても質問とは無関係です。

    キャンセル

  • 2019/04/24 15:11

    自分でも申しておりますが、とてもスマートではないですが・・・。
    「2) 何らかの方法で3行目を削除したい」のひとつの解 にはなっていませんでしょうか?

    キャンセル

  • 2019/04/24 16:15

    これ、単純に3行目に何が入っていても削除されますよね。
    質問内容からすると目的には合致していないと思います。

    キャンセル

  • 2019/04/24 16:21

    ははぁ、そういう意味ですね。質問者さんの状況がわからないので。逼迫しているのかどうか、仮に逼迫しているのであれば、まず、現在の問題を解決したいということもありますので。
    とりあえず、今の 現象のみを解決するという一つの方法として提示しておりました。
    ご指摘ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.82%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る