HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2010
0416
ようむテキストファイルの検索について11解決


ようむ

リンク

2010/4/16(Fri) 11:57:25|NO.31992

初めまして。HSPを始めて3週間程度の者ですが自己解決できず悩んでおりますので
アドバイス頂きたく思います。

PC情報を取得するために「あるテキストから1行ずつ読み込み、
該当する文字列を検索してhitすればその行のある部分を抽出して
表示する。」というツールを開発しています。

検索する文字列がソースのように同じ文字列の場合、読込を頭からではなく
hitした次の行から読み込まないと当然1hit目がずっと表示される結果になります。

getstr の第3パラメーターにstrsizeをインクリメントしてあげれば動くと思っているのですが
3文言目あたりから桁ズレなどが起こってしまいました。

読み込むテキストは

Total Memory 1:512M
Total Memory 2:1024M
Total Memory 3:512M
Total Memory 4:1024M

だとして

実行後に
1:512Mslot1
2:512Mslot2
3:512Mslot3
4:512Mslot4

と表示するにはソースのどこを直せばよいでしょうか?
お手数ですがアドバイスお願いいたします。



notesel memlist
noteload "test.txt" button gosub "終わり",*owari i = 0 cnt2 = 0 name = "Total Memory" gosub *findlist totalram = find3 mes ""+totalram+"slot1" i++ name = "Total Memory" gosub *findlist totalram2 = find3 mes ""+totalram2+"slot2" name = "Total Memory" gosub *findlist totalram3 = find3 mes ""+totalram3+"slot3" name = "Total Memory" gosub *findlist totalram4 = find3 mes ""+totalram4+"slot4" stop *owari end ;検索ルーチン *findlist repeat notemax getstr list,memlist,i i += strsize find1 = instr(list,0,name) if find1 > -1{ noteget find2,cnt2 + cnt find3 = strmid(find2,12,10) cnt2 = cnt return} loop find3 = "none" return end



この記事に返信する


木村

リンク

2010/4/16(Fri) 16:10:00|NO.31993

 HSPにはノートパット関連命令があるのですから、それを利用すれば良いかと思います。
以下は一例

memlist="Total Memory 1:512M\nTotal Memory 2:1024M\nTotal Memory 3:512M\nTotal Memory 4:1024M" button goto "終わり",*owari notesel memlist repeat notemax noteget find2,cnt ;cnt番目の行データをfind2に取得 mes "『" + Findlist(find2,"Total Memory ") + "』\t\t<<Slot" + (cnt+1) + ">>" loop stop #module #defcfunc Findlist str list,str name,local find3,local mid find3="none" ;返し値の初期値を定める mid=list ;dateはエイリアス故にstrmidの第一引数に成り得ないので注意 repeat if strlen(mid)-cnt < strlen(name) : break if strmid(mid,cnt,strlen(name)) = name : find3=strmid(mid,-1,strlen(mid)-strlen(name)-cnt) : break loop return find3 ;find3が関数Findlistの返し値となる #global *owari end
 とりあえず、
>>hitすればその行のある部分を抽出して
 の『ある部分』がどこを指しているのかよく分からなかったので、『検索文字列の直後から
行の終了に至るまでの文字列』を返すようにしました。何か間違いがありましたらご指摘くだ
さい。



ようむ

リンク

2010/4/16(Fri) 16:36:31|NO.31994

木村様。アドバイスありがとうございます!
>>hitすればその行のある部分を抽出して
今回の場合は"Total Memory"より後ろの部分なので12文字目から10文字ほど抜くソースになっています。
>>find3 = strmid(find2,12,10)
今回はソースの一部分で、メモリ以外の構成も拾うようにしているので変数を使用して文字列により変えています。

頂いたソースですが、まだまだ私の使ったことがない関数などがあり(#module,#defcfuncなど)
理解できてない部分があります。一つ一つ意味を調べて、理解しながら学習していこうと思います。

こう言ったことを人に効いたことが無く、うまく伝わらないんじゃないかと・・・・思っていたのですが、
こんなに早く解決の糸口が見つけることができました。
本当にありがとうございます!



ANTARES

リンク

2010/4/16(Fri) 23:59:13|NO.31999

>1:512Mslot1
>2:512Mslot2
>3:512Mslot3
>4:512Mslot4

1:512Mslot1
2:1024Mslot2
3:512Mslot3
4:1024Mslot4
ですよね?

 この場合、ノートパッド命令を使うのは無駄で、
いたずらにスクリプトを複雑にするだけです。
 なお、メインルーチンのi++は不要です。

*findlist j=instr(memlist, i, name) if j<0 { find3="none" } else { i+=j+strlen(name) j=instr(memlist,i,"\n") if j<0: j=strlen(memlist)-i find3=strmid(memlist,i,j) i+=j } return



ANTARES

リンク

2010/4/17(Sat) 00:35:18|NO.32001

 あ、getstrを使ったほうがいいかな?

*findlist j=instr(memlist, i, name) if j<0 { find3="none" } else { i+=j+strlen(name) getstr find3,memlist,i,'\n': j=strsize i+=j } return



ようむ

リンク

2010/4/17(Sat) 01:30:44|NO.32002

ANTARES様、ご返答ありがとうございます。

>>1:512Mslot1
>>2:1024Mslot2
>>3:512Mslot3
>>4:1024Mslot4
>>ですよね?
はい、ご指摘の通りです。コピペの際間違えてしまいました。

getstrを使った、こちらのスクリプトの方が今の私には理解しやすそうです。
ノートパッド命令よりも動作が速いですね!
CPU-ZのテキストファイルからCPU情報やメモリ情報を拾うスクリプトも
無事に動かせましたので、こちらのほうで継続して開発していきたいと思います。

ありがとうございました!!



ようむ

リンク

2010/4/17(Sat) 01:45:14|NO.32003

余談でよいので教えて頂きたいのですが、
私が最初に作成したスクリプトで1行目2行目までは拾えるのに
3行目から桁ずれやバッファーオーバーしてしまう原因は何だったのか
教えて頂けないでしょうか?

i++の部分は文字列検索後に1文字ずらすことにより2回目以降の検索を
行うのに必要だと思い入れていました。実際回目はうまくいくのですが
3回目から検索に引っかからなかったり動作がおかしくなりました。

ご指摘してもらえると次に活かせると思いますのでよろしくお願いいたします。



通りすがり

リンク

2010/4/17(Sat) 02:59:21|NO.32004

検索ルーチンの部分を下のに書き換えると分かりやすいかも。


;検索ルーチン *findlist repeat notemax getstr list,memlist,i dialog ""+list //listの内容を確認 i += strsize find1 = instr(list,0,name) if find1 > -1{ noteget find2,cnt2 + cnt dialog find2 + "\n" + cnt2 + "\n" + cnt //find2,cnt2,cntの内容を確認 find3 = strmid(find2,12,10) cnt2 = cnt break} loop if find1=-1 : find3="none" return

2つほど解決策を。
1つ目は、cnt2が期待通りの動作になっていないようなので、これを修正します。
この場合はcnt2にcntを代入するのではなく、cnt+1を足してやればいいみたいです。多分。

2つ目は、instrの時にlistの中から検索したのですから、
notegetで新たに読み出さずに素直にlistからstrmidする方法です。
見つかった場合に、strmid(list,find1+strlen(name),strlen(list))のようにすれば楽かと。

あ、どちらの策を取っても途中のi++は不必要になります。
i++をつけるとたまたま2行目の頭文字が消えて検索に引っかからず、3行目を検索し、
cntが1になってnotegetで指定した行がちょうど良くなった、という話ですね。

思ったように動かない時は、変数の内容をdialogで表示すると何かに気付けるかもしれません。



amm

リンク

2010/4/17(Sat) 21:19:31|NO.32026

もう解決してるみたいで余計なお世話かもしれんが。
正規表現使った方がずっと簡単だとおもう。


#include "mod_regexp.as" notesel memlist noteload "test.txt" button gosub "終わり",*owari matches list,memlist,"Total Memory (\\d):(\\d+M)" repeat stat mes list(cnt,1)+":"+list(cnt,2)+"slot"+(cnt+1) loop stop *owari end



ようむ

リンク

2010/4/19(Mon) 10:02:14|NO.32096

通りすがり様。アドバイスありがとうございます。

dialogで状況を出す方法は目から鱗ですね。dialog命令も普通に
使ってますが状況確認の為に使うと言うことは思いつきもしませんでした・・。
いつもmes命令で出して見づらかったです。

今回のサンプルソースですと正しく動くようですが、
実際に使用しているコードですと位置情報がずれてしまってますので
調べながら書き直していきたいと思います。

ありがとうございます!

amm様、アドバイスありがとうございます。

正規表現ですと、今回みたいな場合は良いのですが
実際に使用されている構成情報のテキストですと
例えばHDDのサイズの項目は「size」と表記されています。
「size」の単語は他にもメモリサイズ、キャッシュのサイズ
など複数該当する場合に使用すると、コード自体が
複雑化してしまいそうです。

そのため各デバイス固有のタイトルを見つけ、
そこから何行目に拾いたい情報があるかという
コードにしました。

頂いたアドバイスは非常に勉強になりますので感謝いたします!



SYAM

リンク

2010/4/19(Mon) 11:26:44|NO.32098

>dialogで状況を出す方法

老婆心ながら


dialog "状況" ,2 : if(stat==7):end

…のようにして確認する習慣をつけるといいのです。
うっかり何度もループするところに [OK]ボタンしかない dialog 命令を入れると、閉じても閉じても出てきて終了もできなくなってプチいらつきます。



ようむ

リンク

2010/4/19(Mon) 14:09:58|NO.32100

SYAM様。ありがとうございます。

確かにdialogの2ならいつでも終了できますね。
検索するテキストは3000行ぐらいあるので、毎回だと滅入ってしまいますね。
dialogの使い方は知ってましたけど思いつきませんでした・・・。



アドバイス頂いた皆様へ
おかげさまでコードを書き直して満足のいく結果が得られています。
勉強になる部分もたくさんありましたし、いろいろな使い方があるのだなと思いました。
本当に感謝いたします。ありがとうございました!



ONION software Copyright 1997-2023(c) All rights reserved.