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


HSPTV!掲示板


未解決 解決 停止 削除要請

2012
1017
金麦文字列のうち「」に囲まれた部分を抽出したい8解決


金麦

リンク

2012/10/17(Wed) 23:37:11|NO.50039

文字列から一部分の抽出(スクレイピング)について相談です。


■文字列 A
こんにちは、鈴木です。
座右の銘は「俺がやらなくても誰かやる」です。
よろしくおねがいします。


■文字列 B
はじめまして、佐藤と申します。
千葉県に住んでいます。
口癖は「働きたくねぇなぁ」です。
どうぞよろしくお願いいたします。


上記の文章は一例ですが、このような文字列が格納されている変数から
「」(かぎ括弧)の中にある文字列だけを抽出し、それを別の変数へ
代入したいと考えています。

しかし…

・かぎ括弧が始まるまでの文字数や行数 が一定ではない
・かぎ括弧が終わってから文字列末尾までの文字数 も一定ではない
・かぎ括弧内の文字列の文字数 も一定ではない
・マルチバイト文字が含まれる

という障害があり、instrやstrmidではうまい対応方法が思いつきませんでした。
恐らくこれはスクレイピングの基本中の基本だとは思うので、私が考えすぎというか
何か根本的な見落としをしている可能性があるのではないかとも思うのですが…

まとめると
『とある長い文字列の中から "「" と "」" の間にある文字列だけを取り出したい』
ということなのですが、スマートに行うにはどういったアプローチがあるでしょうか。



この記事に返信する


spider

リンク

2012/10/17(Wed) 23:48:53|NO.50040

ここでスウリプト書いてしまうと余り質問者のためにならないと思うので
やり方を書きます。
instr関数でかぎかっこのインデックス求めてstrmid関数で取り出しでできます。

詳しくは自分で考えて。



spider

リンク

2012/10/18(Thu) 00:05:58|NO.50042

連続投稿失礼。
上の自分の回答がいつものへびの画像じゃないのは
べつの機体で書き込んでいるからです。
いつもと別人じゃないです。

一応誤解を避けるために書きました。



F

リンク

2012/10/18(Thu) 08:14:38|NO.50047

instrとかstrmidとか難しいから、簡単にpokeとpeekでまとめてもいいかと。

sdim _str _str ="=u「こ」w求v「か「き」せ」け「こ」「さしがねж」「おれは「てん匹気ぁ廚覆里澄」" dim _lpar dim _lparc dim _rpar dim _rparc dim _stpe repeat strlen(_str) _stpe =peek(_str,cnt) if ($81 <=_stpe and _stpe <=$9f) or ($e0 <=_stpe and _stpe <=$ef){ //shift-jisでは2バイト文字の前半がこれ //ここがないと"=u"とかで誤爆する if _stpe =129{ switch peek(_str,cnt+1) case 117 //"「"を示す _lpar(_lparc) =cnt _lparc++ continue cnt+2 swbreak case 118 //"」"を示す _rpar(_rparc) =cnt _rparc++ continue cnt+2 swbreak swend } continue cnt+2 } loop if _lparc !_rparc :mes "括弧に過不足があるので対象外" :stop _lpar(_lparc) =2147483647//番兵。処理を単純にするために用いる。 _rpar(_lparc) =2147483647//http://ja.wikipedia.org/wiki/%E7%95%AA%E5%85%B5 sdim _resp,,_lparc dim _oucnt dim _oucnt2 dim _nest repeat _lparc _oucnt =cnt sdim _respt if _lpar(_oucnt+1) >_rpar(_oucnt){//入れ子ではない repeat _rpar(_oucnt) -_lpar(_oucnt) -2 poke _respt,cnt,peek(_str,_lpar(_oucnt)+cnt+2) loop _resp(_oucnt) =_respt }else{//入れ子であるために対処する repeat _lparc -_oucnt+1,1 if _lpar(_oucnt+cnt) >_rpar(_oucnt){ _nest =_oucnt +cnt -1 break } loop repeat _nest -_oucnt+1 _oucnt2 =cnt repeat _rpar(_oucnt+_oucnt2) -_lpar(_nest-_oucnt2) -2 poke _respt,cnt,peek(_str,_lpar(_nest-_oucnt2)+cnt+2) loop _resp(_oucnt+_oucnt2) =_respt loop continue _nest+1 } loop repeat _lparc mes "「"+_resp(cnt)+"」" loop stop
strrepとか、文字列操作命令は難しいと思ったらこうしてもいいと思う。



osakana

リンク

2012/10/18(Thu) 13:57:30|NO.50048

抽出をただするなら色々やり方は有ると思いますが
スマートにこだわるならば
#include "mod_regexp.as"
で正規表現を使用するのが良いと思います。



FunnyMaker

リンク

2012/10/18(Thu) 14:16:53|NO.50049

すでに F さんがすごいのを作っていますが、"「」"が一組に限定されているなら、
こんなのだと簡単かと。


文字列A = "こんにちは、鈴木です。\n座右の銘は「俺がやらなくても誰かやる」です。\nよろしくおねがいします。" mes 文字列A + "\n" + "(↑原文)\n\n(↓抽出文)" 対象 = 文字列A : gosub *抽出 mes 結果 mes "\n\n\n" 文字列B = "はじめまして、佐藤と申します。\n千葉県に住んでいます。\n口癖は「働きたくねぇなぁ」です。\nどうぞよろしくお願いいたします。" mes 文字列B + "\n" + "(↑原文)\n\n(↓抽出文)" 対象 = 文字列B : gosub *抽出 mes 結果 stop *抽出;抽出処理 num1_抽出(0) = instr(対象,0,"「");最初の"「"までのバイト数 num1_抽出(1) = instr(対象,num1_抽出(0),"」");最初の"「"から最初の"」"までのバイト数 結果 = strmid(対象,num1_抽出(0) + 2,num1_抽出(1) - 2) return



FunnyMaker

リンク

2012/10/18(Thu) 14:20:07|NO.50050

ご存じないみたいですのでちょっと...↓

複数行の文字列だからといってinstrを使う際に場合分けする必要はありません。
改行の部分には本当は「\n」があるだけですから、それが「2」としてカウントされます。



GENKI

リンク

2012/10/20(Sat) 01:38:38|NO.50087

1バイト単位で文字列操作は難しいしなかなかうまくいかなかったり大変です。
osakana さんがおっしゃられているのが一番簡単です。

#include "mod_regexp.as" a={" こんにちは、鈴木です。 座右の銘は「俺がやらなくても誰かやる」です。 よろしくおねがいします。 "} mes match(a,"「.+」") ;最初と最後を消して利用してください。 mes match(a,"「.+(?=」)") ;最初の一文字目だけ消して利用してください。 mes match(a,"(?<=「).+(?=」)") ;修正がいらないはずですが(?<=pattern) が対応していないorz

正規表現は覚えると普段のプログラミング作業でも活用できるんで便利ですよ。



金麦

リンク

2012/10/21(Sun) 01:53:54|NO.50112

みなさんありがとうございます。
いろいろなアプローチがあり非常に参考になりました。
pokeとpeekを使うというのは思いつきませんでした…

やはり文字列操作はマルチバイト文字の処理が複雑になりがちですね。
スマートさと柔軟性を考えると特に正規表現が便利そうな印象を受けました。
ただやはり文字列操作命令を組み合わせるなどの工夫は必要そうですね。

今後の拡張の可能性なども踏まえて、いただいたご意見を参考に進めてみます。
とても助かりました。ありがとうございました。



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