ここから質問投稿すると、最大4000ポイント当たる!!!! >>

関数「exists」と「defined」の違いが分かりません。

「exists」はハッシュにしか使えないため「defined」
より特殊な関数なのでしょうが。

$a{$i} = 0 unless defined $a{$i};
$a{$i} = 0 unless exists $a{$i};

↑の二つの文は等価ですよね?

このQ&Aに関連する最新のQ&A

A 回答 (2件)

キーが存在するがその値が未定義、という場合があるので等価ではない。



---------------------------------------------
my %a = ("x"=>undef);

if ( defined($a{"x"}) ) {
print qq(\$a{"x"} is defined\n);
}
else{
print qq(\$a{"x"} is not defined\n);
}
if ( exists($a{"x"}) ) {
print qq(\$a{"x"} exists\n);
}
else{
print qq(\$a{"x"} does not exists\n);
}
    • good
    • 0
この回答へのお礼

非常に分かりやすい例をありがとうございました。

お礼日時:2008/01/16 01:20

先に回答されているように等しくありません。


exists は $hash{'key'} の key 自体が存在しているか調べられます。

exists の結果が偽なら defined も偽になりますが、
defined が偽でも、key 自体が存在していれば exists は真を返します。
    • good
    • 0
この回答へのお礼

回答1への補足、ありがとうございました。

お礼日時:2008/01/16 01:21

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

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

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

Qサブルーチンを認識しません。

perlプログラムで
サブルーチンの中で、別のサブルーチンを呼び出していますが、
なぜか認識しません。
KCatchでは以下の表示をしています。
Catch: Mon Sep 22 07:56:36 2003
-------------------------------------------------
[regist.cgi:375:die] Undefined subroutine &main::lock called.
>&lock;
-------------------------------------------------
regist.cgi with Perl 5.00502 for freebsd

サブルーチン名には頭に & を付けて呼び出しています。
サブルーチンは、スクリプトの最後にまとめてあります。
同じサブルーチンは、他のスクリプトでも利用していますが、
エラーは出ていないのですが。

何が原因か、わかりません。
関係ないかもしれませんが、プログラム最初の方でuse strict;の宣言をしています。
他のサブルーチンも認識しません。
KCacthの表示は同じ
&main::サブルーチン名 called になっています。
よろしくお願いします。

perlプログラムで
サブルーチンの中で、別のサブルーチンを呼び出していますが、
なぜか認識しません。
KCatchでは以下の表示をしています。
Catch: Mon Sep 22 07:56:36 2003
-------------------------------------------------
[regist.cgi:375:die] Undefined subroutine &main::lock called.
>&lock;
-------------------------------------------------
regist.cgi with Perl 5.00502 for freebsd

サブルーチン名には頭に & を付けて呼び出しています。
サブルーチンは、スクリプト...続きを読む

Aベストアンサー

下記前提でよいでしょうか。
&lock(); ・・・(lockを呼び出している箇所)

sub lock    ・・・サブルーチン:lockの定義
{
・・・
}
上記は1つのソースファイル上にある。

とすると、考えられるのは、
1.undef (&lock); により未定義にしている。
2.__DATA__のあとにsub lockを定義している為、サブルーチンとして認識されない。(__END__も同様)
です。上記の2点はOKでしょうか?

Q複数ファイルの読み込みについて

perl初心者です。

あるディレクトリから拡張子がdataであるファイルを全て読み込みたいのですが、方法がわかりません。
cshで書くと
foreach arg (*.data)
コマンド $arg

のようになりますが、perlだと
foreach $arg (@arg){
コマンド $arg

となりますよね?
引数がリストなのでよくわかりません。
そもそもperlではできないのでしょうか?


それともう一点ですが、ファイルオープンするときに
foreachループの中で
open(FILE, "$arg");
とすることは可能ですか?
上の質問と組み合わせて全てのファイルを開いて作業を行いたいので。

説明が下手ですいません。補足しますのでよろしくお願いします。

Aベストアンサー

while(<*.data>)
{
## $_には、*.DATAなファイル名が格納されている。
open(F,"$_"); ##openする。
while(<F>)
{
##読み出された内容が$_に格納されている。
print $_; ##出力してみる。
}
}

というのが最短コーディングです。

Qファイルの行数取得

超初心者です。

いま、表計算的なスクリプトを記述しています。

あるファイルの行数を取得する関数ってあるんでしょうか?

ファイルに記述されている数値を足したり引いたりするのですが、forを使っての計算の際にファイルの行数が必要となりました。

Aベストアンサー

Perlにですね。ないはずです。
行数とはファイルに書かれた改行文字の個数ということなので
実際にファイルを全て読み込まないと行数はわかりません。
以下のように色々な方法があると思います

#### 単純な例
$a = 0;
open FD, "<file.txt" || die $!;
while (<FD>) {
$a++;
}
close FD;
print "行数:$a\n";

### 少しマニアックな方法
open FD, "<file.txt" || die $!;
@a = <FD>;
close FD;
print "行数:" . ($#a + 1) + "\n";


### 反則的方法(外部コマンド) ... UNIXの場合
print "行数:" . `wc -l file.txt` . "\n";

Qひとつの命令を複数行に記述

検索してもあまり解説見かけないなぁと思うのですが、(どこが本家かわからないのでとりあえず放置)

VBでいう_に該当するものは何ですか?
ソースが長くなって見にくくなっているので、対処したいのですが。

hoge = "じゅげむじゅげむごごうのすりきれ" _ '←次の行に送る
& "かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ" 

Aベストアンサー

Perlは、VBと異なり行の概念がありません。
VBではステートメント区切り子が存在しないため、改行がステートメントの区切りとして扱われ、例外的につなげるときに「_」を使うわけですが、
Perlの場合はステートメント区切り子セミコロン「;」がステートメントの区切りになっていますので、セミコロンを打たない限り、何行に分かれてもひとつのステートメントとして扱われます。
したがって、回答としては「そのまま改行してOK」です。
上記の例なら、

$hoge = "じゅげむじゅげむごごうのすりきれ" .
"かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ";

という感じです。
当然ながら、文字列中での改行はダメなので、上記のようにいったん「"」を閉じて、文字列結合演算子「.」で接続することに成ります。

Qperlで配列の要素が空なのを知るには?

教えてください。

例えば、perlの次の様な要素が3つある配列で、

@t = ('A',,'C');

2要素目が空で有ることを判別したいのですが、どうしたら良いでしょうか?

Aベストアンサー

'' と比較する.

QPerlで特定行から特定行までを抜き出したい

皆さんのお知恵をお貸し頂ければ幸いです。

Perlで以下のようなことをしたいと考えています。
例えば、次のようなテキストファイルがあったとします。

example.log
==================================
aaaa
hogehoge
test
okok
perl
script
==================================

上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。
イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

このような場合、どういう風にすればいいのでしょうか?
恐れ入りますが、ご教授頂ければ幸いです。

それでは、どうぞよろしくお願い致します。

Aベストアンサー

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $flag = 0 }
  elsif ($flag) { print "$data\n" }
}
close FH;

で、もっと略したいPerlな人だとこんな感じ。Perl独特の記法がふんだんに使われているので、勉強するには不向きかもしれませんが^^;

open FH, "example.log" or die $!;
while (<FH>) {
  print if /^hogehoge$/ .. /^perl$/ and !/^(?:hogehoge|perl)$/;
}
close FH;

※インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $fl...続きを読む

QPerlでファイルを読み込み重複データの検索

お世話になります。
次のようなテキストファイルを読み込んで重複を探し、表示したいのですが、Perlで、どのようなコードを書けば良いのでしょう。

尚、重複チェックは2通りあります。
パターン1 例えば1,2が2回以上出現する
パターン2 1,2と2,1や2,3と3,2は重複とみなす。

テキストファイル
1,2
1,3
1,4
1,5
2,1
2,3
2,4
2,5
3,1
3,2
1,2

チェック後の表示
1,2,重複
1,3,重複
1,4,
1,5,
2,1,重複
2,3,重複
2,4,
2,5,
3,1,重複
3,2,重複
1,2,重複

宜しくお願いします。

Aベストアンサー

解説:
while(<DATA>){#実際は、ファイルハンドル(か<>)になるべき所、DATAにしておくと、__END__から読み込める、この場合は、別にテキストファイルを作るのがめんどくさかったからと、これだけで実行(追試)ができるという意味
chomp;#末尾の改行を切り捨てる、引数が無い時は$_現在の読み込み行に対して実行される
$data[$i++]=$_;#現在の行を、あとで元データとして利用するために配列に入れておく
$test{$_}++;#既にあったかどうかテストするために行データをキーにハッシュにしておく、値は、出現回数
($a, $b)=split ",";#今読み込んでる行を「,」で分離する
$test{"$b,$a"}++;#逆順の並びでハッシュに登録
}
foreach $x (@data){#元のデータを順に取り出す
print "$x";#オリジナルの表示
print ",重複" if($test{$x}>1);#ハッシュで、2回以上カウントされていたら重複しているって表示する
print "\n";#改行をつけて一行分処理終わり
}
__END__

解説:
while(<DATA>){#実際は、ファイルハンドル(か<>)になるべき所、DATAにしておくと、__END__から読み込める、この場合は、別にテキストファイルを作るのがめんどくさかったからと、これだけで実行(追試)ができるという意味
chomp;#末尾の改行を切り捨てる、引数が無い時は$_現在の読み込み行に対して実行される
$data[$i++]=$_;#現在の行を、あとで元データとして利用するために配列に入れておく
$test{$_}++;#既にあったかどうかテストするために行データをキーにハッシュにしてお...続きを読む

Q「ご連絡いたします」は敬語として正しい?

連絡するのは、自分なのだから、「ご」を付けるのは
おかしいのではないか、と思うのですが。
「ご連絡いたします。」「ご報告します。」
ていうのは正しい敬語なのでしょうか?

Aベストアンサー

「お(ご)~する(いたす)」は、自分側の動作をへりくだる謙譲語です。
「ご連絡致します」も「ご報告致します」も、正しいです。

文法上は参考URLをご覧ください。

参考URL:http://www.nihongokyoshi.co.jp/manbou_data/a5524170.html

Q参照配列の要素数の求め方は?

リファレンス配列の要素数は、$#では求められないのでしょうか?

-------------------------------------
foreach $i(0 .. 3){
$hash->[$i] = $i * 100;
}
print "\%hashの要素数->$#hash\n";

$ref = \%hash;
print "\%{$ref}の要素数->$#{$ref}\n";
-------------------------------------

Aベストアンサー

んーと
配列のリファレンスをつかった例でしたら...


foreach $i(0 .. 3){
$hash[$i]->{'v'} = $i * 100;
}

# 配列@hashへのリファレンス
$ref = \@hash;

# デリファレンス
@copy = @{$ref};

print "\$refの要素数->$#$ref\n";
print "\@copyの要素数->$#copy\n";


あと配列 @hash と連想配列 %hashは内容は別物ですので
期待した動きにならないのだと思います...


人気Q&Aランキング