検索システムを作ろうと思っています。テキストファイル(このソースではgreetings.txtです。)の中にある文章をキーボード入力で1文字でもヒットすれば抜き取って表示させたいのですが、以下のソースをコマンドプロンプトで実験したところ「Q、Y,S,M、と記号」で検索すると全ての文章がヒットしてしまいます。他の文字では問題無くヒットするのですが…。perlを始めてばかりでまだまだわからないことだらけです。いちおう本やネットで検索したんですがさっぱりわかりません。どなたかどうかお力を貸していただけませんか?
#!C:\Perl\bin\perl
$kensaku = <>;
$ans = eval $kensaku;
open(IN, "greetings.txt");
while ($line = <IN>){
if($line =~ /$ans/i){
print "$line";
}
}
No.5ベストアンサー
- 回答日時:
Perlはそのままでは日本語(をあらわす文字コード)を理解しません。
そのため、
>for %i in (オ ツ イ シ) do echo %i | hexdump
00000000: 83 49 20 0A .I .
00000000: 83 63 20 0A .c .
00000000: 83 43 20 0A .C .
00000000: 83 56 20 0A .V .
オ、ツ、イ、シのそれぞれにI, c, C, Vを見つけてしまいます。
この問題はPerlに日本語文字コードを理解させればいいので、
たとえば以下のようにスクリプトを書き換えます。
$kensaku = <>;
$ans = $kensaku;
chomp $ans;
$ans = Encode::decode('sjis', $ans);
open(IN, '<:encoding(sjis)', "greetings.txt") or die "can't open data file\n";
while ($line = <IN>){
chomp $line;
if($line =~ /$ans/i){
$line = Encode::encode('sjis', $line);
print $line, "\n";
}
}
use encoding プラグマを使うという方法もありますが、
問題を起こしやすいのでお勧めしません。
この回答への補足
上記のスクリプトで試してみましたが、
Undefined subroutine &Encode::decode called at Z:\a.pl line 7, <> line 1.
というエラーが出てスクリプトがうまく動きませんでした。sakusaker7さんは、うまく動くことができたのでしょうか?encodeというものが調べていくうちに多少はわかったのですが、どういうふうにモジュールをつけたら良いのかわかりません…。引き続きご回答をいただきたいと思います。
No.7
- 回答日時:
んーエラーが再現しません。
スクリプトは
use Encode;
$kensaku = <>;
$ans = $kensaku;
chomp $ans;
$ans = Encode::decode('sjis', $ans);
open(IN, '<:encoding(sjis)', "greetings.txt") or die "can't open data file
\n";
while ($line = <IN>){
chomp $line;
if($line =~ /$ans/i){
$line = Encode::encode('sjis', $line);
print $line, "\n";
}
}
__END__
$kensaku = <>;
#$ans = eval $kensaku;
$ans = $kensaku;
open(IN, "greetings.txt");
while ($line = <IN>){
if($line =~ /$ans/i){
print "$line";
}
}
で、greetings.txtは以下の通り
湘南乃風
KREVA
monkey Majik
ACIDMAN
175R
ケツメイシ
レミオロメン
大塚愛
以下実行例です。
D:\work\script\perl>perl find.pl
愛
大塚愛
D:\work\script\perl>perl find.pl
ケ
ケツメイシ
D:\work\script\perl>perl find.pl
南
湘南乃風
perl -w スクリプト名 のように -w オプションを指定して実行してみてください。
何か警告は出てきませんか?
すみません。スクリプトにちょっと余計なものを打ち込んでしまったみたいです…。コピペしてみたら普通に動作しました^^;申し訳ないです。お手数おかけしてすみませんでした。何回もご親切に教えてくださって本当に感謝しています。また何かあればここに来ようと思います。
No.6
- 回答日時:
すみません。
スクリプトをコピーするときに一行抜けてしまったようです。スクリプトの先頭に
use Encode;
という行を加えてください。
これでコンパイルが通るようになるはずです。
この回答への補足
お礼を投稿しておいて申し訳ないのですが、今度は日本語のデータが検索できなくなってしまいました。ファイルオープンに使っている「greetings.txt」には、
湘南乃風
KREVA
monkey Majik
ACIDMAN
175R
ケツメイシ
レミオロメン
大塚愛
という日本語を含んだ文字列が含まれているのですが、これを検索しようとすると、
F:\perl>perl sisaku.pl
南
Quantifier follows nothing in regex; marked by <-- HERE in m/? <-- HERE ?/ at si
saku.pl line 14, <IN> line 1.
F:\perl>perl sisaku.pl
愛
Quantifier follows nothing in regex; marked by <-- HERE in m/? <-- HERE ?/ at si
saku.pl line 14, <IN> line 1.
F:\perl>perl sisaku.pl
ケ
Quantifier follows nothing in regex; marked by <-- HERE in m/? <-- HERE P/ at si
saku.pl line 14, <IN> line 1.
といったようなエラーが出てきます。これを改善することは可能でしょうか?何度もすみません。お手数おかけしますがお願いします。
ありがとうございました。無事コンパイルも通り、正常にプログラムを動作させることができました!また何かわからないことがあれば質問させていただきます。本当にありがとうございました!
No.4
- 回答日時:
ああ、大文字じゃなくてq,y,s,m は小文字なんですね。
わかりました。
これは
$ans = eval $kensaku;
でeval してるからです(なんのため?)
q, y, s, m はそれぞれ特別な意味を持つものなので、evalすると
消えてなくなるようです。
s は s///, y は y/// qは シングルクォートの代わりの記号の指定 mは m///
の指定に使われますから。
:\work\script\perl>perl -de 42
oading DB routines from perl5db.pl version 1.28
ditor support available.
nter h or `h h' for help, or `perldoc perldebug' for more help.
ain::(-e:1): 42
DB<1> print eval "q"
DB<2> print eval "@"
DB<3> print eval "Q"
Q
だから、
DB<4> print eval "tr"
DB<5>
これも消えます。
なるほど、そういうことだったんですか。どうもうまくいかないので本を読みあさっていた所、evalを使っている例文を見つけまして、適当にくっつけたところあんな感じで半分成功の半分失敗状態になってしまいました…。いや、意味がわかっていないのでは完全に失敗ですね;
わかりやすいご説明どうもありがとうございました!大変勉強になりました。ですが、この後また問題が起こりまして…。詳しいことは、guci-okさんへの補足に書いてあります。できればもう少し力を貸していただけませんか?お願いします。
No.3
- 回答日時:
うまくいかないという具体例を挙げてもらえませんか?
スクリプトと補足されたgreetings.txt をそのままコピペして試してみましたが
D:\work\script\perl>perl err.pl
g
Good morning
good bye
good night
D:\work\script\perl>perl err.pl
Q
D:\work\script\perl>perl err.pl
a
thank you
スクリプトにちょっとまずいところはありますが、問題点が明らかに
なっていないのでとりあえずは指摘しないでおきます。
この回答への補足
私の場合では、Qと打ったところ、「greetings.txt」の全文が表示されてしまいました。具体的に申しますと
F:\perl>perl sisaku.pl
q
Good morning
hello
good bye
thank you
good night
F:\perl>perl sisaku.pl
F:\perl>perl sisaku.pl
y
Good morning
hello
good bye
thank you
good night
F:\perl>perl sisaku.pl
s
Good morning
hello
good bye
thank you
good night
F:\perl>perl sisaku.pl
m
Good morning
hello
good bye
thank you
good night
F:\perl>perl sisaku.pl
@
Good morning
hello
good bye
thank you
good night
のように、「Q、Y、S、M」と「記号」で入力すると、「greetings.txt」の中に「Q」は一つも入ってないはずなのに、「greetings.txt」の全文が表示されてしまいます。
ちなみに他の英数字で入力すると、ちゃんと期待通りの結果が返ってきます。
F:\perl>perl sisaku.pl
g
Good morning
good bye
good night
F:\perl>perl sisaku.pl
a
thank you
F:\perl>perl sisaku.pl
h
hello
thank you
good night
sakusaker7さんは、見たところ「Q」で入力しても何も表示されずうまくいっているみたいですね。なぜでしょうか?perlのバージョンの問題でしょうか?ちなみに使っているperlのバージョンは5.8です。
No.2
- 回答日時:
キーボード入力で指定するのは、正規表現ですか、マッチさせたいテキストですか?
後者ならquotemeta関数を通します。
$kensaku = <>;
chomp $kensaku;
$ans = quotemeta($kensaku);
この回答への補足
すみません、さっきのでいちおう解決はしたんですが、日本語の文章も検索させて見ようと思い、「greetings.txt」の内容を変更し、自分の知っている歌手などの名前を適当に入れてみました。内容はこうです。
greetings.txt
湘南乃風
KREVA
monkey Majik
ACIDMAN
175R
ケツメイシ
レミオロメン
大塚愛
これで動かしてみると「i」,「c」,「v」で入力して検索をかけたときになぜかカタカナのデータまで表示されてしまいます。実際の表示では、
F:\perl>perl sisaku.pl
i
monkey Majik
ACIDMAN
レミオロメン
F:\perl>perl sisaku.pl
c
ACIDMAN
ケツメイシ
F:\perl>perl sisaku.pl
v
KREVA
ケツメイシ
こんな感じです。調べてみたところ、「i」は「オ」に、「c」は「ツ」と「イ」に、「v」は「シ」にヒットしてしまうようです。どうしてこのようなことが起こるのでしょうか?また、この問題を解決するにはどうしたらいいのでしょうか?一度解決させていただいたのに、何度も質問をして申し訳ありませんが教えていただけないでしょうか。お願いします。
guci-okさんの言われたとおりにやってみたらちゃんと期待通りの結果が得られました!quotemeta関数を調べてみたところ、どうやら文字列中の記号が正規表現のメタ文字として扱われるのを防ぐものらしいですね。だから記号等で検索した場合、全文の内容を表示されてしまったんですね。以外とあっさりした解決で以外でした^^;
質問の内容に不足していた部分があるにもかかわらず教えてくださり、本当にどうもありがとうございました!また機会があれば質問させていただきたいと思います。
No.1
- 回答日時:
greetings.txt の中身もわからんし「実際にはどのようにキーボードから入力したか」もわからんのだから, かなり回答しずらいんだけど...
ちなみに, なんで eval してるの?
この回答への補足
greetings.txtの内容は
Good morning
hello
good bye
thank you
good night
といったものです。例えばここから「g」とキーボードから入力することで「Good morning」「good bye」「good night」が表示されるようにしたいのです。「a」と入力すれば「thank you」が表示されたり。試行錯誤したのですが、ちゃんとした結果が得られません。引き続き回答お願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- SEO 関係ないページを検索エンジンが拾ってしまう 1 2022/05/14 11:16
- Visual Basic(VBA) InputBoxでキャンセルボタンを押したらファイル自体を閉じたい 3 2022/07/23 17:52
- その他(プログラミング・Web制作) atcoder python コードへの助言 2 2022/08/12 15:31
- SEO 意図しないページが検索ヒットする問題 2 2022/05/19 14:35
- Excel(エクセル) 製品番号での整列と、検索に関して 3 2023/06/28 19:20
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- Firefox(ファイヤーフォックス) Firefoxでグーグルの検索画面が変です 2 2022/09/20 19:25
- 英語 提示文の"hence"の前にピリオドがない理由と文の構造について 8 2022/03/24 10:48
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
bashのgrepで複数の検索、かつ...
-
perlスクリプト s/^\\s+//; ...
-
実行時パラメータを使用するとE...
-
PerlでIPアドレスを取得する方法
-
例外処理のフローチャートの記...
-
Excel VBAでリンク切れをチェッ...
-
VBA This Workbookモジュール...
-
VBAで別モジュールへの変数の受...
-
Excel VBAで、ユーザーフォー...
-
SOAP::Liteを利用したい!
-
エクセルVBAでシートモジュール...
-
「デバイスは PRN を初期化でき...
-
Excel VBA 『Call』で呼び出す...
-
VBでグローバル変数を宣言するには
-
教えて下さい。
-
ユーザー定義関数に#NAME?が返...
-
laravel 本番環境でメールが送...
-
UWSCのスクリプトにラグが発生...
-
'Range'メソッドは失敗しました
-
【vba】フォームに書いてあ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
bashのgrepで複数の検索、かつ...
-
エラー
-
Pod::Usageで日本語を使用する...
-
perlでactive directoryに登録
-
perlスクリプト s/^\\s+//; ...
-
perl+shiftjisで5c文字化けの対...
-
UTF-8で書かれたHTMLファイルを...
-
XML::XPathで日本語検索するには
-
メールフォームからの受信メー...
-
何時間後を求める。
-
実行時パラメータを使用するとE...
-
Excel VBAでリンク切れをチェッ...
-
Excel VBA 定義されたプロージ...
-
例外処理のフローチャートの記...
-
ArduinoのジャイロモジュールMP...
-
ユーザー定義関数に#NAME?が返...
-
「デバイスは PRN を初期化でき...
-
VBAで別モジュールへの変数の受...
-
エクセルVBAでシートモジュール...
-
Excel VBA 『Call』で呼び出す...
おすすめ情報