open(IN, $FILE);した時に、
<IN>のx行目とn行目だけを取り出したいと思っています。
これまでは@array=<IN>;としてきたのですが
ファイルが大きくなると非常に遅くなってしまいます。
@arrayに<IN>を格納することなく処理をする事は出来るのでしょうか。
よい方法がありましたら教えて下さい。

A 回答 (2件)

こんな感じでよいのでは?



 open IN, $file or die;
 while (<IN>) {
   if ($. == $x) { chomp($line_x = $_); }
   elsif ($. == $n) { chomp($line_n = $_); }
 }
 close IN;

 print $line_x;
 print $line_n;

改行除去は必要に応じて行ってください。
    • good
    • 0
この回答へのお礼

解決することが出来ました。
ありがとうございました。

お礼日時:2001/08/17 09:10

単純に考えて、例えば $x = <IN>; をループで回しながら x 行目と n 行目の


場合のみ必要な処理を行い、それ以外を捨てる、というのではダメなのでしょうか?

この回答への補足

レスありがとうございます。
最初青らくだ本などを読んで、
----------------------
open(IN, $file);
$. == $x and $line = $_ while <IN>;
close(IN);
print $line;
----------------------
というようにしてみたのですが
これだとx行目は処理できますがn行目を指定できないので
困ってしまい質問しました。
よろしくお願いします。

また@arrayだと一度格納してしまえば
配列を空にしてしまうまで$array[$x]のように参照できるのに、
上記のものでは処理をおこなう度に、
毎回ファイルをオープンしなければならないのですが
本当にこれで配列に格納した場合より
メモリが節約されているのでしょうか…?

補足日時:2001/08/16 13:47
    • good
    • 0
この回答へのお礼

解決することが出来ました。
ありがとうございました。

お礼日時:2001/08/17 09:10

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

このQ&Aと関連する良く見られている質問

Qperlスクリプト s/^\s+//;  s/\s+$//;  return wantarray ? @out : $out[0]; について

自作の掲示板を作ろうと思い、perlの勉強をしている者です。人様の作ったスクリプトを解析しています。以下のスクリプトはライブラリに記述されていたものです。


sub tttt {
my @out = @_;
for (@out) {
s/^\s+//;
s/\s+$//;
}
return wantarray ? @out : $out[0];


このスクリプトなんですが、 s/^\s+//; の部分の「+」と s/\s+$//; の部分の「+$」、 また「return wantarray~」 の三つの部分のスクリプトが、どういった働きをしているの分かりません。専門書やウェブ上のリファレンスも色々調べたのですが・・。

分かる方いらっしゃいましたらご教授下さると幸いです。よろしくお願いします。

Aベストアンサー

まず前2つの「+」は,正規表現における,「直前の表現を一回以上繰り返し」をあらわします.
「\s」は空白文字一文字を表す正規表現ですので,「\s+」は,「一文字以上の空白文字」になります.
次に,最初の「^」と2番目の「$」は,その正規表現がどこに現れるかを示す記号です.それぞれ,先頭と最後尾にあることを示します.
したがって,「^\s+」は,「最初に空白が一文字以上ある文字列」に,
「\s+$」は「行末に空白が一文字以上ある文字列」にヒットします.
置換構文sはご存知なんですかね.すなわち,この2文で,行の最初と最後の空白を消しているんです.

次に, wantarray ですが,
http://www2u.biglobe.ne.jp/~MAS/perl/ref/wantarray.html
によると,このサブルーチンttttを呼び出すときに,何を返り値にしているかで真偽が決まる関数です.
呼び出す時に配列を希望していたら @out 全体を,変数を希望していたら $out[0]だけを返します.

Qopen (FILEHANDLE,"< $filename") or die "エラーメッセージ";について

下記プログラムでperl_read_writes.txtを出力すると、中身が表示されるのですが、a_perl_read_writes.txt等に名前を変更すると、当然エラーが起きます。
が、die "$filenameを開けません。";の部分の
$filenameを開けません。という文章が出力されないのですが、どなたか原因分かりませんか?

==================================================
#!/usr/bin/perl
print "Content-type: text/html;charset=Shift-JIS", "\n\n";

# HTMLの出力
print "<html>\n";
print "<body>\n";
print "ファイルの読み書き<br>\n";

$filename='/usr/local/apache/htdocs/aaa/bbb/perl_read_writes.txt';
# ファイルオープン
open (FILEHANDLE,"< $filename") or die "$filenameを開けません。";
...以下省略
==================================================

よろしくお願いします。

下記プログラムでperl_read_writes.txtを出力すると、中身が表示されるのですが、a_perl_read_writes.txt等に名前を変更すると、当然エラーが起きます。
が、die "$filenameを開けません。";の部分の
$filenameを開けません。という文章が出力されないのですが、どなたか原因分かりませんか?

==================================================
#!/usr/bin/perl
print "Content-type: text/html;charset=Shift-JIS", "\n\n";

# HTMLの出力
print "<html>\n";
print "<body>\n";
print "ファイルの...続きを読む

Aベストアンサー

# > ・・という文章が出力されないのですが、

# ↑どこに出力されないのか? というか、
# エラーメッセージを通常どこで確認しているかが不明ですが、


# エラーメッセージを標準エラーメッセージファイル"STDERR"以外に、
# 画面にも出力するように指定する。
use CGI::Carp qw(fatalsToBrowser);

my $filename = '/usr/local/apache/htdocs/aaa/bbb/a_perl_read_writes.txt';
open (FILEHANDLE,"< $filename") or die "$filenameを開けません。";

# 上記を、手元の
#  WinXP Pro.SP2 + Apache 1.3 + ActivePerl 5.8.4(810) + shift-jis
# で試すと画面(ブラウザ)に以下が出ます。

# (結果)
# /usr/local/apache/htdocs/aaa/bbb/a_perl_read_writes.txtを開けません。at c:\apache\cgi-bin\nu\hoge.pl line nn.

# key word : Perl STDERR, use CGI::Carp

# > ・・という文章が出力されないのですが、

# ↑どこに出力されないのか? というか、
# エラーメッセージを通常どこで確認しているかが不明ですが、


# エラーメッセージを標準エラーメッセージファイル"STDERR"以外に、
# 画面にも出力するように指定する。
use CGI::Carp qw(fatalsToBrowser);

my $filename = '/usr/local/apache/htdocs/aaa/bbb/a_perl_read_writes.txt';
open (FILEHANDLE,"< $filename") or die "$filenameを開けません。";

# 上記を、手元の
#  WinXP Pro.SP2 + Apac...続きを読む

Q@b = grep(/マッチパターン/, @a);でなく@a = grep(/マッチパターン/, @a);でOKについて

@b = grep(/マッチパターン/,@a);だと配列@aの中でマッチするものを探して@bに入れる・・・というのは理解できるんですが、
@a = grep(/マッチパターン/,@a);とし、
foreach $_ (@a) {
print $_;
}
で参照した場合、@aの中のマッチパターンにマッチするのだけ表示されますけれども、ここでマッチしないのは削除されるのでしょうか・・。

@aから@aにいれる・・・となる事について、どのように@aにマッチしたものを入れ、マッチしないものは削除されるのかの仕組みについて、ご説明できる方はいらっしゃいますでしょうか(例えば内部的にpopやshiftが機能していて・・・みたいな事なのかな・・とか思うんですけれども)

お手数ですが、ご存知の先生方ご教授願えましたら幸いです。

Aベストアンサー

#1でのTacosanさんの回答の1です。
つまり、
@a = grep(/マッチパターン/,@a);
これは
@aの内容を列挙→ grepに掛ける→条件に合うものだけのリストを作成→作成したリストを代入。
となります。
grepに掛かる前の@aの内容は、代入の際に「丸ごと」破棄されます。

perly.y
/* Binary operators between terms */
termbinop:term ASSIGNOP term /* $x = $y */
{ $$ = newASSIGNOP(OPf_STACKED, $1, IVAL($2), $3);
TOKEN_GETMAD($2,$$,'o');
}

op.c

OP *
Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
{
dVAR;
OP *o;

(略

if (is_list_assignment(left)) {
static const char no_list_state[] = "Initialization of state variables"


という具合なので、代入の左右両辺が同じ変数かどうかのチェックは多分やってません。

#1でのTacosanさんの回答の1です。
つまり、
@a = grep(/マッチパターン/,@a);
これは
@aの内容を列挙→ grepに掛ける→条件に合うものだけのリストを作成→作成したリストを代入。
となります。
grepに掛かる前の@aの内容は、代入の際に「丸ごと」破棄されます。

perly.y
/* Binary operators between terms */
termbinop:term ASSIGNOP term /* $x = $y */
{ $$ = newASSIGNOP(OPf_STACKED, $1, IVAL($2), $3);
TOKEN_GETMAD($2,$$,'o');
}

op.c

OP *
Perl_newASSIGNOP...続きを読む

Q$wfurikae = 1 if ( &ccom::getShukujitsu( &com::tD( $wwy,$wwm,$wwd )) ne '' );がよく

$wfurikae = 1 if ( &ccom::getShukujitsu( &com::tD( $wwy,$wwm,$wwd )) ne '' );

というスクリプトがあったのですが、

$wfurikae = 1 の後に;もいれずifがきています。

違和感があります。

どのような意味になるのでしょうか。

宜しくお願い致します。

Aベストアンサー

そのまんまだと思いますよ。
if 以下の条件が真の時 $wfurikae = 1となります。
Perlはいろいろな書き方ができますので、こういう書き方もありです。
英語の文法の並びにする書き方です。

Q; を単独で使う

1行飛ばして読み込みさせたくて、seek の代わりに
<IN>; と書いてみたんだけど、それで成功した
CGIもあれは、失敗したものもありました。
<IN>; と書く間違いですか?

Aベストアンサー

いわゆる「1行読み捨て」ならば、
  <IN>;
でOKです。
(「scalar(<IN>);」でもOKなのですが、タイプが面倒なので私は書きません。)
ちなみに shift は引数に配列を期待するので、
  shift(<IN>);
だとエラーになるはずです。

そもそも、(概念的な)テキストデータ処理で seek は使いません。
seek は、フォーマットが分かっているデータや、固定長のレコードデータなどに用います。
<IN> では \n までを読み込みますが、seek が使われているということは、データの区切りに \n は使われていないのではないでしょうか。


おすすめ情報