• ベストアンサー

Perlで読み込んだファイル内の行数の検索について

教えてください。 読み込んだファイル内にある空行・コメント行・処理行を一つのスクリプトで表示する書き方をおしえてください。 超初心者なので 今のところ、ファイルのオープンしかできていません。 #ファイルをオープンします open(F,"upload.cgi")|| die "upload.cgiをオープンできません:$!\n"; #ファイルを読みます while(<F>){ #内容を表示 print; } #ファイルを閉じます close(F); どこで、何の処理をしているかもコメントしていただけると助かります。 よろしくお願いします。

  • Perl
  • 回答数2
  • ありがとう数15

質問者が選んだベストアンサー

  • ベストアンサー
  • bilbo
  • ベストアンサー率100% (1/1)
回答No.2

yatokesaさんの書いてた," "を含むような一般的な文についてのコメント の抜き出しは,ちょっと強引な書き方ですが,次のような正規表現でできないでしょうか? /^([^\"\#]*\"[^\"]*\")*[^\"\#]*(\#.*)$/; print "$+\n"; ちなみに, $_ = "\"not comment # not comment\" not comment \"not comment\" # comment\"comment\"#comment"; $_と,これに対する上の正規表現で抜き出した$commentを表示させると, 入力 "not comment # not comment" not comment "not comment" # comment"comment"#comment コメント # comment"comment"#comment となります. yatokesaさんの書いて下さったのと組み合わせて使ってください. 正規表現の説明ですが... [^\"\#]* : "と#以外の繰り返しにマッチ \"[^\"]*\" : "で囲まれた領域にマッチ ([^\"\#]*\"[^\"]*\")*[^\"\#]* : "で囲まれた領域と,#を含まない文字列にマッチ (\#.*)$ : コメントにマッチ. この前に上の正規表現が書いてあるので,この部分は"で囲まれてない#にマッチします. つまりコメントにマッチします. $+は正規表現で最後にマッチした部分です. 厳密にチェックしてないので抜けがあるかもしれませんが,こんな感じでしょうか.

marumaru2828
質問者

お礼

具体的に教えていただきありがとうございます。 まだ、記号を見慣れていないのと、置き換える処理がわからないので 難しいですが、がんばって習得していきます。 また、わからないところを質問すると思うので、その時は教えて下さい!

その他の回答 (1)

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.1

空行の判定は length($_) == 0 か $_ eq '' コメント行は、処理行の後にあるコメントもカウントするとなると少し面倒です。" " (ダブルクォーテーション)や ' ' (シングルクォーテーション)や / / パターン内、@# とかの # はコメントではないのでそれを判定しなければなりません。(正規表現でできるのかな?) 単純にコメントしかない行を判定するのなら、 /^[\s\t]*#/ で判定できます。 それ以外は処理行と言うことですね。 あとは、if 分で判定して、それぞれをカウントアップすればOKですね。

marumaru2828
質問者

お礼

空行は結構かんたんに検索できるのですね! 本当に初心者なので、まだちょっとわからないですが、なんとかがんばってみます。ありがとうございます!

関連するQ&A

  • Perlでのファイルの扱いでつまづいております。

    やりたいことは、"ファイルAを読み取り、その内容に処理を施したものをファイルBに書き込むという処理"です。 その上で、"ファイルBに書き込んだ内容を書き込みと同時に読み取り、 その上である条件にマッチした文を書き換える"といったことを実現したいです。 もともとのファイルの容量が非常に大きいので、何度もループを使うといったことはなるべく避けたいため、 ファイルBの書き込み・読み込み・書き換えを同時に行いたいのですが、 そもそもそういったことは可能なのでしょうか。 ※また、もともとのファイルの容量が非常に大きいので配列を使わず行う、 ということが前提条件としてあります。 現在のスクリプトの簡略化したものが以下となります。 open LOGFILE,"< /○○/ファイルA" || die("die"); open NEWLOG,"+< /△△/ファイルB" || die("die"); $new = <NEWLOG>; while($yomitori = <LOGFILE>){ if(ある条件1){ print NEWLOG "$kakikomi\n"; } if(ある条件2){ ファイルBの書き換えの処理 $new =~s/\n/ $kakikae\n/; print NEWLOG "$new"; } } close(NEWLOG); close(LOGFILE); 上記スクリプトで、ファイルAからファイルBへの書き込み、ファイルBの読み取りまではできておりますが、 ファイルBの書き換えは実現しておりません。 以上、お詳しい方がいらっしゃいましたら宜しくお願い致します。

    • ベストアンサー
    • Perl
  • Perl 教えてください。

    下記のような簡単なスクリプトなんですが、なぜかサーバーにアップすると動きません。 ローカルでコマンドプロンプトから直接実行するとまともに動作します。 パーミッションは「755」と「705」でやってみましたが。 perlのパスは合っていますし、実際同じ場所に置いた他のCGIは動作します。 #!/usr/bin/perl open (DT, "<./data/***/***.csv") or die "File '***.csv' Open Error."; @data = <DT>; $data[0] = ",,,,,,\n"; open (OUT,">./data/***/***1.csv") or die "File '***1.csv' Open Error."; print OUT @data; close (DT); close (OUT); 原因が分からず困っています。 解決策でなく、原因と思えるだけの回答で結構ですので何卒よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • perlで文書を読み込み検索置換したい

    MAC OS Xを使用しています。 検索置換のプログラムをperで作成し、Applescript上で呼び出したいのです。 実際はファイルメーカーのスクリプトの中でApplescriptを記述してその中で呼び出したいのです。 do shell script "perl ~.pl"という感じで使えるのではないかと 下記のようなサンプルスクリプトを見つけたのですが 内容の更新の仕方がよく分かりません。 perlについては全くの初心者でいろいろ調べたのですがよく理解できませんでした。 検索置換したいのですが、どういうふうに書けばいいのでしょうか。 (2)の部分を教えて下さい。宜しくお願いします。 use strict; use warnings; use File::Copy 'move'; # (1) ファイルの内容を読み込む my $file = 'F:\共有\PERL\test.txt'; open my $fh, '<', $file or die qq/Can't open file "$file": $!/; my $content = do {local $/; <$fh>}; close $fh; # (2) 内容の更新 ▼をリターンに置き換えたいのです。 $line =~s/▼/\n/; # (3) 一時ファイルへの書き出し my $temp_file = "$file.$$." . int(rand 10000); open my $temp_fh, '>', $temp_file or die qq/Can't open file "$file": $!/; print $temp_fh $content; close $temp_fh or die qq/Can't open file "$file": $!/; # (4) 一時ファイル名を元のファイル名に変更 move $temp_file, $file or die qq/Can't move "$temp_file" to "$file": $!/;

  • perl use strict; と ファイルハンドルについて

    perl use strict; を使うと、単純なエラーが防げると認識していますが、下記スクリプトでは役に立たなかったようで、このエラーを探すのに苦労しました。 他にも、どこかのサブルーチンでsortを使ったスクリプト中で、$aを使った時もおかしな挙動をしたことがあります。 use strict;の使い方は正しいと思うのですが、エラーを出してはくれないものでしょうか? また、このようなエラーをしないために安全なプログラムの書き方はありますか? use strict; open(F,"<file.txt"); while(<F>){ &abc($_); } close(F); sub abc(){ my $str = shift @_; open(F,">>file2.txt"); print F $str; close(F); }

    • ベストアンサー
    • Perl
  • Perlのプログラミングについて

    Perlのプログラミングでつまづきました。 # ファイルから指定文字列を含む行を収集する # 入力ファイルのオープンと読み込み print( "入力ファイル名?" ); $n = <STDIN>; chomp( $n ); open( FIN, "<$n" ) or die "入力ファイルオープンエラー: $!\n"; $n = @a = <FIN>; close( FIN ); print( "$n 行読み込みました\n" ); # 行の収集 print( "検索文字列?" ); $x = <STDIN>; chomp( $x ); $ptn = $x; #指定の文字列 $x = @b = grep( /$ptn/, @a ); print( "$x 行見つかりました\n" ); # 出力ファイルのオープンと書き出し print( "出力ファイル名?" ); $y = <STDIN>; chomp( $y ); open( FOUT, ">$y" ) or die "出力ファイルオープンエラー: $!\n"; print FOUT ( $ptn, "\n" ); print FOUT ( $x, "\n" ); print FOUT ( @b ); close( FOUT ); というプログラムで実行すると C:\My Perl\pl>perl プログラムの実行.pl 入力ファイル名?sample1.txt 168 行読み込みました 検索文字列?k 45 行見つかりました 出力ファイル名?out3-24.txt 続行するには何かキーを押してください . . . となり出力ファイルの中身が表示されません。 どこを間違えているのかご指摘いただけないでしょうか?

  • Perl オープン関数について

    Perl オープン関数について いつもお世話になっております。 オープン関数でわからないことがあるのでご教示お願い致します。 ■test.cgi■ open(FILE, ">sled/$log") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; ■bbstest.cgi■ open(FILE, ">>sled/$loglog") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; 上記のtest.cgi側では「>」これが1個で書き込まれるのですが bbstest.cgi側では「>」これ1つだけですと、すべての内容がリセット され、その時入力した内容だけ残ります。 それを「>>」にすると追加はされるのですが、 test.cgi側では 上へ上へと内容は追加されていくのに対し bbstest.cgi側では 下へ下へ追加されていきます。 書込方法は、両方共 unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); このようにしているのですが、 なぜ、同じ処理で、書込方法がかわるのでしょうか? 目的は上へ上へがいいのですが。。。

    • ベストアンサー
    • Perl
  • perlでCSV形式ファイルのアップロード

    本日、同じ質問をしたものです。 前回の問題は解決したのですが、ファイルがアップロードできないで悩んでします。 CGIのプログラムは以下のソースです。 #! c:/perl/bin/perl use CGI; # CGIヘッダーの出力 print "Content-type: text/html\n\n"; my ($query,$fileName); $query = new CGI; $fileName = $query->param('fileName'); open(OUT, ">./a.csv"); binmode(OUT); while(read($fileName,$buffer,1024)) { print OUT $buffer; } close(OUT); close($fileName); #ファイルハンドルをcloseしています。 exit ; ファイルは、作られるのですが、中身が書き込まれません。 どなたか教えてください。 お願いします。

    • ベストアンサー
    • Perl
  • 行を指定して削除する方法PERL

    ある文字を検索して、その行を含む&1行前と2行後ろの行までを削除するスクリプトを書きたいのですが、上手くいきません。 検索して行番号を獲得して、 $rowという変数に入れました。 それをさらに $a :1行前 $b :2行後ろの行番号に格納しました。 問題は削除するところが上手く行きません。 next if で $aから$bの行番号を削除して、と頼んでいるのですが、空のファイルに上書きされてしまいます。 お願いです。この方法で何が間違っているかを教えてください! #!/opt/perl/5.8.0/bin/perl -w print "Content-type: text/html\n\n"; use CGI qw(:standard); use CGI::Carp qw/fatalsToBrowser/; $filename = "../XML/link.xml"; $new = "../XML/link.xsl"; open(FILE, $filename) or die "Can't open `$filename': $!"; while (<FILE>) { if($_ =~ /HRWeb/){ #print "$."; $row = $.; $a = $row-1; $b = $row+2; print "HRWeb delete rows $a through "; } } &delete ($a, $b); sub delete{ open( OLD, "< $filename" ); open( NEW, "> $new" ); while ( <OLD> ) { next if /$a/../$b/; # copy everything but $a through $b print NEW $_; }print "$a deleted $b"; close( OLD ); close( NEW ); rename( $filename, "$filename.orig" ); rename($new, $filename ); }

    • ベストアンサー
    • Perl
  • 1ファイルずつ読み込みたい

    ウィンドウズ環境でactive perlを利用しています。 あるディレクトリーの中に2000位のファイルが入っており、このファイルを読み込んで置換処理を行うため下記のようなperlを作っています。 1ファイルはおおよそ3000行くらいです。 foreach(<*.html>) { open(IN_FILE, $_) || die; open(OUT, ">$_.tmp") || die; @record=<IN_FILE>; foreach $record (@record){ $record =~s/aaa/bbb/isg; } print OUT @record; close( IN_FILE); close( OUT); rename("$_.tmp", $_) ; } 当たり前かもわかりませんが、メモリー不足になり処理が中断します。 ディレクトリーの中のファイル数を600程度に少なくすると処理が完了します。 そこで質問なのですが、ディレクトリーの中のファィルを一度に全部読み込まず、1ファイルずつ順次読み込んでいくことはできないでしょうか。 最初の1行目のforeachをwhileに変えたりしたのですがうまくいきません。 対応策あればご教示ください。

    • ベストアンサー
    • Perl
  • perlでCSV形式ファイルのアップロード方法

    perlでCSV形式ファイルのアップロード方法を教えてさい。 htmlで <HTML> <BODY> <FORM action="excel読み込み.cgi" enctype="multipart/form-data" method="post"> フレアシステムのファイル: <INPUT type="file" name="upload_file" size="60"><BR> <INPUT type="submit" value="読み込み"> </FORM> </BODY> </HTML> として、ファイル名の指定をして、読み込みボタンを押すと、excel読み込み.cgiを呼び出すのですが、プログラムの内容が表示されるだけで終わってしまいます。 excel読み込み.cgiのプログラムは以下の内容です。 #! c:/perl/bin/perl use CGI; $query = new CGI; $filename = $query->param('upload_file'); while(read($filename, $buffer, 2048)) { $file .= $buffer; } @files = split(/\\/, $filename); ($basename, $exp) = split(/\./, $files[-1]); $new_file = $basename . "." . $exp; # ファイルを指定ディレクトリにコピー #open(OUT, "> c:\\foo\\$new_file"); open(OUT, "> c:\\$new_file"); binmode(OUT); print(OUT $file); close(OUT); print "Content-type: text/html\n\n"; print "[$basename] [$exp]\n"; print "正常終了\n"; exit; CGIのプログラムを色々と調べて、別のないようにしても同じようにプログラムがそのまま表示されてしまいます。 どなたか教えてください。 宜しくお願いします。

専門家に質問してみよう