perl5でunixの"wc"や"grep -c"みたいに1つのファイルの中からある文字列の個数を
カウントするスクリプトを作ろうとしています。

ファイルは256文字×10万行くらいのテキストで、
検索する文字列は15文字前後×40個(例えば「apple-000001」「lemon_orange」など)です。

どのようなスクリプトを組んだら効率よく各文字列をカウントできるのでしょうか?
それよりwcやgrep -cを40回行った方が早いのでしょうか?

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

A 回答 (3件)

最終的な速度については分かりませんが,Perl で効率良く実現しようというのであれば,配列(下の例では @pattern)に照合する文字列を入れておいて,ファイルから一行読むごとに,



foreach $pattern (@pattern) {
$count{$pattern} += /$pattern/g; #行の内容は $_ に入っていると仮定
}

とかしてやればよいのではないでしょうか。
一行にパターンが必ず一回しか現れないのであれば,2行目は,

$count{$pattern}++ if (/$pattern/);

とかすることも可能でしょう。

上記コードでは,パターン照合回数は grep を使ったときと同じですが,ファイルI/Oの回数は 1/パターン数 で済みます。が,パターン照合の速度そのものは grep のほうが速いでしょうから,最終的にどちらが速いかはやってみないと分かりません。

ちなみに,Perl のパターンマッチング処理は,一般に sed と同等或いはより高速だと言われているので,sed を使う意味はあまりないと思います。

この回答への補足

1000行25パターンのテストデータでやってみたところ
grep(25回)はperlの1.5倍処理時間がかかりました。
ということでperlで処理したいと思います。
ありがとうございました。

補足日時:2002/01/18 18:35
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
まさにperlやりたかった内容です!
grepと比較検討してみたいと思います。
#見た目的にはperl処理かな ^ ^;)

お礼日時:2002/01/18 09:02

> また、systemコマンドでgrepを呼んだとすると、その結果をperlで処理するのはどうするのでしょうか?



パイプを使います。perl は普段使わないので、怪しいのですが、こんな感じになるはず。

open IN, "grep なんとかかんとか |" or die "error\n";
while ( <IN> ) {
  何か $_ を使った処理。例えば…
  print;
}
close IN;


> ファイルは1つです。その中で検索する文字列が40個あります。

ああ、そういうことなのね。ちょっと迷いますね。

sed で、一行一単語にばらしつつ、検索する文字列を含む行だけを抽出しておいて、その出力を perl で
処理してカウントして行くのが一番軽いかな?
    • good
    • 0
この回答へのお礼

さらなるご回答ありがとうございます。
パイプの使い方大変参考になりました。
sedのほうは、atonさんが回答していただいた処理と比較検討してみたいと思います。

お礼日時:2002/01/18 08:57

直接の回答にはならないかもしれません。



> それよりwcやgrep -cを40回行った方が早いのでしょうか?

wc や grep は、複数のファイルを一度に処理できますから、起動は一回だけで
済みます。

# 特定の単語を探すのであれば、wc には無理ですね。

perl もかなり早いんですが、(環境にもよりますが)grep なんかは、それなりに
速さを要求されてきて育ってきたプログラムですから、下手なスクリプトを書くよりは
ずーっと早いです。

もし探す文字が、固定で構わない(つまり、正規表現を使わない)のであれば、
fgrep を使うのが一番早いんじゃないかと思います。

この回答への補足

回答ありがとうございます。

>grep は、複数のファイルを一度に処理できますから、起動は一回だけで済みます。
>
ファイルは1つです。その中で検索する文字列が40個あります。
それぞれの個数を調べるにはやはり40回のgrepが必要ですか?

あと、その前後の処理をperlで書いてしまっているので、perl上で処理できるように
したいというのがあります。
また、systemコマンドでgrepを呼んだとすると、その結果をperlで処理するのはどうするのでしょうか?
grepの結果をファイルに一度結果を出力する必要があるのでしょうか?

補足日時:2002/01/15 19:08
    • good
    • 0

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

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

Q歯を削るときなんで痛く感じるのですか? 歯を削るだけなら痛くないのに

歯を削るときなんで痛く感じるのですか?
歯を削るだけなら痛くないのに

Aベストアンサー

歯は基本的に硬組織と呼ばれる硬い結晶で出来ています。一番表面はエナメル質と呼ばれ この硬い結晶成分のみでできています。この部分は削っても痛みは全くありません。
2層目は象牙質(dentin)と呼ばれやや硬い組織で出来ています。そして歯の中央・最深部は歯髄・いわゆる神経と呼ばれる軟組織(普通の神経・血管組織)となっています。
この2層目の象牙質には 歯髄から細い繊維が入り込んでいてエナメル質直下まで 神経組織が伸びています。従って 歯を削る時にこの象牙質を削ると いっしょに神経組織まで削ってしまう事になり 強い痛みを発する事になるんです。普通 象牙質だけを削るよりも、この神経繊維の末端・つまりエナメル質と象牙質の境目を削る時の方がはるかに強く痛みを感じますねぇ~ 痛みを感じない部分から突然痛みを感じる部分に入った瞬間に急激な痛み・あの独特の痛みがあるわけです。
もちろん 歯を削る時の痛みは、神経だけの問題ではありません。タービンと呼ばれる機器・ドリルによって削る事が多いですが、この切削具の振動・回転する摩擦熱等が歯の知覚組織に伝わる事も痛みの原因となります。最近では、タービンを使わないレーザー光線による切削も多くなり、削る時の痛みは大幅に軽減されています。また、機器の振動を抑える工夫もなされており、機器の振動と似た振動を他の箇所に与える事により、痛みの閾値を上げてしまう(わかりやすく言うと 振動で神経を麻痺させて痛みを感じにくくする事)方法も行われています。

さて、通常の治療で歯を削る時は、神経のある歯(虫歯が小さい場合)や 神経を取る処置の場合、麻酔を使うことがほとんどでしょう。
えまく麻酔が効けば 痛みは全く感じなくなります。ただ、歯科の麻酔は歯の神経を麻痺させねばなりません。歯の神経の出口は 歯の根の先端・つまり骨の中にあるんです。
これを麻酔することはなかなかに難しい事なんです。普通 顎の骨は硬く厚い骨が多く なかなか麻酔薬が内部に浸潤してくれません。かなりの力を入れて圧力をかけないと 硬い骨を通り越してくれませんので、歯科の麻酔はそれだけでも痛いのです(^o^;...この時 骨の厚さによって麻酔が効く効かないが別れますね~
実は同じように 歯のエナメル質の厚さによっても削る時の痛みに差があるのです。例えば同じ歯でも、切端部・先っぽの方はエナメル質が厚いので少々削っても痛みません。逆に根元に近い部分はエナメル質が薄く 象牙質がすぐ直下にあるために痛みが感じやすいと言えます。
また、年齢によっても痛み方に大きな差があります。歯は生えたばかりはまだ幼弱で 歯髄が大きく象牙質が薄いのです。それだけ削る時に神経に近くなってしまい痛みが出やすいですねぇ~
逆に生えてから何十年も経った歯は・・・・つまり老人の歯は 多少削っても痛みません。これは長い間に神経が退化したり象牙質が石灰化して硬化したために 痛みを感じる神経が退化して・あるいは無くなってしまったからです。麻酔を使わずにどんなに削っても 全く痛まないことも しばしばあります。

いずけにしても痛みの感じ方には大きな個人差があります。痛いと感じたなら 左手を挙げて・・・・・ヽ(;^^)/ まぁ、歯科医師にお伝え下さい。

歯は基本的に硬組織と呼ばれる硬い結晶で出来ています。一番表面はエナメル質と呼ばれ この硬い結晶成分のみでできています。この部分は削っても痛みは全くありません。
2層目は象牙質(dentin)と呼ばれやや硬い組織で出来ています。そして歯の中央・最深部は歯髄・いわゆる神経と呼ばれる軟組織(普通の神経・血管組織)となっています。
この2層目の象牙質には 歯髄から細い繊維が入り込んでいてエナメル質直下まで 神経組織が伸びています。従って 歯を削る時にこの象牙質を削ると いっしょに神経組織...続きを読む

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歯を削る(レーザー、カリソルブ、水流、ドリル)比較について

【質問・要点】
昨日、インレーが取れました。そこで、少し削って新しいインレーを入れると思うのですが、以下4つを考えたのですが、いったい、どれが最も良い治療法なのでしょうか?

レーザー
カリソルブ
水流で削る
ドリルで削る

【一応私が考える判断基準】
最も歯を削る体積が小さい治療法、
術後、2次齲蝕が最も少ない治療法
最も痛くない治療法

他に、もっと良い治療法やアドバイスがあれば、ご教示、何卒、宜しくお願い致します。

Aベストアンサー

歯科医です。
>レーザー
>カリソルブ
>水流で削る
>ドリルで削る
沢山質問されていますが
ここでまとめて。
まず、レーザーでインレーが入れられるほど削るのはできないです。削除量が圧倒的にすくなくて、綺麗な形態に削ることができないから。
カリソルブも同様です。
水流で削るのは歯に対して現在そういう器具はありません。
ドリルで削る・・・・ドリルというのは恐らくエアタービンもしくはエンジンのどちらかをさしておられる
のでしょうか。タービンで削ることが一番でしょうね。

インレーがはずれたのではなく
新しい虫歯であるのなら削除量のことを考える余地があります。しかし
何分にもすでにインレーの体積分は歯が失われているので
削除量を少なくする事に意義は見出せません。
さらに虫歯になっていなければ大抵の場合はほとんど削らなくてもよいでしょう。
取れたところがさらに虫歯になっているのであれば
削除量云々言う前に
虫歯をとりさることが肝要です。二次カリエスにならないためにはこれがもっとも大切なことです。
痛くない治療法・・・は麻酔を的確に使用して治療することでしょう。

それから
インレーはわりと易しい技工物ですので
一般的なレベルの技工士さんであれば
十分な適合の良いきれいなインレーを作りますよ。

異種金属が口腔内にあることの是非は討論の余地があるのですが
一般的に言って
接しているところでなければ
大きな問題はおきないです。
接するところではそこに小さな電池ができるようなものなので
電流が流れます。

それよりなにより
一日も早く治療を受けてください。
放置しておくことに良い点は一つもありません。

歯科医です。
>レーザー
>カリソルブ
>水流で削る
>ドリルで削る
沢山質問されていますが
ここでまとめて。
まず、レーザーでインレーが入れられるほど削るのはできないです。削除量が圧倒的にすくなくて、綺麗な形態に削ることができないから。
カリソルブも同様です。
水流で削るのは歯に対して現在そういう器具はありません。
ドリルで削る・・・・ドリルというのは恐らくエアタービンもしくはエンジンのどちらかをさしておられる
のでしょうか。タービンで削ることが一番でしょうね。

イン...続きを読む

Q文字列のカウント

お世話になります

あの、
あいうえお
かきくけこ
さしすせそ
という3組の文字列が有るとします

そのそれぞれの組(あいうえおで1つ)を
として数えるにはどうしたらいいのでしょうか?

例えば
あいうえお+
かきくけこ+
さしすせそ=3
となるようにしたいのですが・・・

Aベストアンサー

nextと入れるとって事はコマンドラインで
やってるという事でしょうか?

とりあえずこんな感じでどうでしょう?

#以下インデントは全角空白で行っています。

open(DB, "hoge.txt");
chomp(@List = <DB>);
close(DB);

$start = 0;
while(1){
 $end = $start+10 < scalar(@List) ? $start+10 : scalar(@List);
 for($i=$start; $i<$end; $i++){
  print "$List[$i]\n";
 }
 while(1){
  print "\ncommand:";
  chomp($cmd=<STDIN>);
  if( $cmd eq "next" ){
   $start = $start+10 < scalar(@List) ? $start+10 : $start;
   last;
  } elsif( $cmd eq "prev" ){
   $start = $start >= 10 ? $start-=10 : $start;
   last;
  } elsif( $cmd eq "end" ){
   exit;
  } else {
   print "command list : next : preview next 10 item\n";
   print " : prev : preview previous 10 item\n";
   print " : end : this system ends\n";
  }
 }
}

違ったらごめんなさい( ´д`)

nextと入れるとって事はコマンドラインで
やってるという事でしょうか?

とりあえずこんな感じでどうでしょう?

#以下インデントは全角空白で行っています。

open(DB, "hoge.txt");
chomp(@List = <DB>);
close(DB);

$start = 0;
while(1){
 $end = $start+10 < scalar(@List) ? $start+10 : scalar(@List);
 for($i=$start; $i<$end; $i++){
  print "$List[$i]\n";
 }
 while(1){
  print "\ncommand:";
  chomp($cmd=<STDIN>);
  if( $cmd eq "next" ){
   $start = ...続きを読む

Q勉強の為に睡眠削るのは確かにダメですが 勉強スケジュール上、このままでは間に合わないという状況では、

勉強の為に睡眠削るのは確かにダメですが
勉強スケジュール上、このままでは間に合わないという状況では、削るのは仕方なくないですか?エナジードリンクなり、使って

Aベストアンサー

まあその前に 遊びの時間は削るはな
その上で足りなければ トイレの時間中や バスや電車の移動中 そして場合によると食事中なども勉強する。
それでも足りない時は 睡眠5時間とかになるかな。

コーヒー 音楽 エナジードリンク ハーブ 辛い食べ物 いろいろ使いながら。
最低必要な睡眠時間ってのは人によっても違うが 短期的なら4時間睡眠でも案外行けると思う。
ただ 何というか 考え方が狭くなるように思う。
ヒラメキが出ないのだな。

別に問題はないと思うのだ。
こういう経験も大切だし 焦りさえしなければ十分得るものはある。
脳にも緩急は必要だし 時にフルスロットルも良い・・が あまり長くやると痛む。

よほど深く眠らないと4時間で2週間以上続けるのは難しかった。
そして6時間程度寝ないと 自律神経系は慣れでなんとかなるみたいなんだが どうもホルモンバランスが悪くなる感じ。
そこは注意すべきかと。

QPerlでシフトコード変換後の文字列長をカウント

PC上のデータに含まれる機種依存文字((1)(2)IIIなど)をEBCDICコードを使用しているホスト機にファイル転送をする時、表示可能な文字に変換を掛けようと思っています。
Perlで変換を行うところまではなんとか辿り着きました。

ところが、(1)を1.に変換すると、PC上では文字数は変わりませんが、ホストにアップロードした時に、シフトコードが入るために、最悪前後に全角文字が入っている場合は、2バイトのプラスになり、ホスト上のデータベースにインポートする時にエラーを引き起こしてしまいます。

これを防ぐため、Perl上で、文字コード変換を行う時にシフトイン&シフトアウトの発生した場合の文字列長のチェックを行いたいのですが、全角文字と半角文字の識別と長さのカウントを行う方法、なにか参考になるサイトがありましたら、教えて頂けると助かります。

よろしくお願いします。

Aベストアンサー

ググると、
「ebcdic->sjis変換で失われたシフト文字分の空白をEncode::CJKConstantsで復活」
http://d.hatena.ne.jp/end0tknr/20090222/1235302471
という記事がありました。

シフト文字分の空白を付け加えて文字数(バイト数??)をカウントするという方法でうまくいかないでしょうか。

Q固定された木材を削る道具は?

部屋のドアを、内開きから外開きに変える計画を立てています。上、左右のドア枠は内側と外側のサイズが同じなのですが、下側のドア枠は削る必要があります。ドアと枠は共に木製です。
そこで質問なのですが、ドア枠のように固定された木材を削る道具は、どういったものが最適でしょうか?
回答、よろしくお願いします。

Aベストアンサー

こんにちは。
どれくらい削るかにもよりますが。

ごくわずかであれば、電動〈仕上げ)サンダーっていう、電動紙やすりみたいな機械があります。
レンタルしてるかもしれないですね。

カンナを使うなら、角は(何種類かの目の粗さの)木工ヤスリを使って、仕上げは紙やすりで。

ところで、ドアの方を削るわけにはいかないんでしょうか?
大工さんが間違えてドア枠を作って取り付けてしまった時に、ドア下部を削ってましたよ。(^^;
問題がなければ、ドアを削った方が得策かと思いますが。

Q大量データから抽出する効率よいperlプログラムは

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aファイルのその行を抽出したい。
grepで実施すると すごい時間がかかってしまうため、効率よい抽出方法をおしえてください。
今回は、完全一致ではなく、Bファイルに入っているリストのURLから始まるものにしたいと考えているので、前の手法(hash連想配列)が使えないと考えております。
Aファイルが容量大きいため、grep処理では1週間たっても終わらないのです。

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aフ...続きを読む

Aベストアンサー

本当に終わるか気になったので、自分のPCで試してみました。
メモリ4Gであれこれ普通に使いながら、次のものです。
ただ、内一個は途中でやめちゃいました。

まず、こんなかんじでdummyファイルを作りました

Ruby
# dummy作成
http://ideone.com/TDxut
→1Gバイトで約2000万件の嘘データ
# フィルタ元リスト作成
→dummyの頭50件の、URL内ドメイン箇所までのリスト

Ruby
# 文字列マッチ
http://ideone.com/xPsku
→約25分

# 正規表現マッチ
http://ideone.com/kvSff
→途中でやめた為不明

GNU/grep
# grep -F -f 元リスト.txt dummy.txt
→1分弱!


ということで、少なくともRubyでは全く太刀打ちできませんでした。
でも、終わる分量ではあると思います。特にPerlならきっともっと早いんでしょう
やっぱりgrepがおすすめですね

Q歯を削る時痛かったを英語で?

教えて頂きたいのですが、歯医者さんで虫歯を削る時に痛かったと英語で言いたいのですが
I was pain when I shave bat tooh.
であってますか?
削るというのもshaveでいいのかわからないのですが、いい単語があれば教えて頂きたいです!

Aベストアンサー

こんにちは。4/11のご質問ではお礼のお返事を有難うございまして。

ご質問:
<I was pain when I shave bat tooh.であってますか?>

以下の点で訂正を要します。

1.I=painではないのでbe動詞はここでは不適です。

2.動詞はhadなどを使って、
I had a pain「痛みがあった」→「痛かった」
とするのが自然です。

3.shaveはどちらかというと「削ぎ落とす」「削ぐ」の意味に近くなります。歯医者でいう「削る」とは、「穴をあけること」ですから、ここはdrillが適切です。

4.I shave:「私が削る」のではないので、ここでは使役動詞haveなどを使って「削ってもらう」にします。
例:
I have my tooth drilled.
「私の歯を、削らせる」→「削ってもらう」

ここでdrilledと過去分詞になっているのは、目的語Oであるmy toothと、補語Cであるdrilledの関係が、受動の関係になるからです。
例:
my tooth is drilled「歯が、削られる」

5.虫歯はbad toothと綴りを正します。

6.以上を踏まえて原文に忠実な訂正例は
I had a pain when I had my tooth drilled by dentist.
「歯医者に歯を削ってもらった時、痛かった」
となります。

7.他にも以下のような表現もあります。
I felt some pain when I had my tooth drilled.
「歯医者に歯を削ってもらった時、少し痛かった」

以上ご参考までに。

こんにちは。4/11のご質問ではお礼のお返事を有難うございまして。

ご質問:
<I was pain when I shave bat tooh.であってますか?>

以下の点で訂正を要します。

1.I=painではないのでbe動詞はここでは不適です。

2.動詞はhadなどを使って、
I had a pain「痛みがあった」→「痛かった」
とするのが自然です。

3.shaveはどちらかというと「削ぎ落とす」「削ぐ」の意味に近くなります。歯医者でいう「削る」とは、「穴をあけること」ですから、ここはdrillが適切です。

4.I shave...続きを読む

Qスクリプトから別のスクリプトファイルへ移動させるには?

初歩的な質問で恐縮です。
ググッてもわからないので、質問させていただきます。

変数『$A』をIF文で処理して、例えば『$A』が数値の3なら、任意のファイルへページ移動させたいのです。

if($A==3){ここの書き方が不明}

(1)ただ単にヤフーのトップページに飛ばしたい場合
(2)$Aをhiddenタイプで、別のスクリプトファイルに飛ばして処理させたい場合

以上です。
よろしくお願い申し上げます。

以上の二種類です。

Aベストアンサー

if($A == 3) {
print "Location: http://www.yahoo.co.jp/\n\n";
}

で平気だと思います。

間違って
print qq|Content-type: text/html\n\n|;
とかを前に入れてしまうとエラーが出ます。

「リダイレクト」で検索をかければいろいろ出てきます。


人気Q&Aランキング

おすすめ情報