人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

特定の文字以降を削除する方法はわかったのですが、さらに複数の条件を加えたところ、当方のスキルでは出来ない状態です。
現在VBScriptである特定の文字以降を削除する方法を考えております。
現在LEN関数などで、特定の文字以降を削除する方法はわかったのですが、
複数の条件を加えたところ、当方のスキルでは出来ない状態です。
以下の条件を満たせるサンプルスクリプトを作成いただけないでしょうか


■文字列操作内容


□文字列処理対象: 「テスト 第XX回」
□文字列処理後の姿: 「テスト」


※文字列処理対象内の「XX」は数字1から3桁の場合があります。
※文字列処理対象内の「第」の前のスペースは半角、全角を含みます。また複数のスペースがある場合も削除対象となります。




上記のように、文字列の中で「第」の後に「XX」という数字2桁(若しくは1桁)がきて、その次の文字が「回」だった場合に
「第」から後ろを削除するというものです。また削除する際に、「第」の前にスペースが存在した場合は
スペースも含め削除というものです。(スペースは半角、全角を含む。また複数のスペースがある場合も全て削除対象)


宜しくお願い致します。

●質問者: gocnia3
●カテゴリ:コンピュータ インターネット
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● a-kuma3
●300ポイント ベストアンサー

こんな感じ。

 data = "テスト 第123回"
 Set re = CreateObject("VBScript.RegExp")
 re.Pattern = "^(.+)[  ]*第[0-9]+回"
 re.Global = True
 Set matches = re.Execute(data)
 result = matches(0).SubMatches(0)  ' これが "テスト" になってます

正規表現オブジェクトというものを使います。
re.Pattern に設定している文字列が正規表現です。
ちょっと分かりにくいですが、[ ] の中には、半角の空白と全角の空白が続けて書いてあります。



windofjuly さんの回答で、VBA じゃなくて VBScript だってことに、今さら、気が付きました。
といっても、ほとんどコードは同じなんですけど。

data = "お試しコードのテスト 第123回"
Set re = new RegExp  ' VBA と、ここだけ違う。
re.Pattern = "^(.+)[  ]*第[0-9]+回"
re.Global = True
Set matches = re.Execute(data)
result = matches(0).SubMatches(0)  ' これが "テスト" になってます

WScript.echo result



追記です。

まだ動かしてないのですが、勉強がてらした3行が何をやってるか教えていただくと幸いです(ぐーぐる先生に聞いてみましたがどうもよくわからない。。)

おっちょこちょいな回答を書いた手前、分かる範囲であれば、何でも答えます (^^;

>re.Global = True

これは、Execute メソッドで、指定した正規表現が一致する個所を見つけたときに、
それ以降も検索するかどうかの指定です。
Global = True だと、一致するパターンが複数あるときに、全て探そうとします。
今回の場合には、True でも False でも、動作に違いが無いんですが、
対象の文字列が "お試しコードのテスト 第123回 (関東支部開催 第25回" のように、
複数繰り返されているような場合に、Execute メソッドの戻りの内容が変わってきます。

>Set matches = re.Execute(data)

正規表現 re.Pattern が表す内容を、文字列 data に対して実行して、検索した結果を返します。
検索結果は、Matches というコレクションになっています。

>result = matches(0).SubMatches(0) ' これが "テスト" になってます

Execute メソッドの戻り値である Matches コレクションは、文字列 data を検索した結果が入ってます。
Matches コレクションは、Match オブジェクトのコレクションです。
先程の、Global プロパティが True だと、要素数が2以上になる可能性があります。

Match オブジェクトが、検索して一致した結果を表しています。
Match オブジェクトは、以下のプロパティと、コレクションを持ちます。

正規表現の説明からした方が良いでしょうね。
"^(.+)[ ]*第[0-9]+回" という正規表現を分解すると、

^文字列の先頭を表す
(.+)任意の文字「.」の一回以上の繰り返し「+」
()でくくってあるのは、後で使いたいから
[ ]*[ ]が、半角の空白、もしくは、全角の空白一文字で、「*」がゼロ回以上の繰り返し
そのまま「第」に当たります
[0-9]+半角の 0から 9までの文字のどれかの一回以上の繰り返し
そのまま「回」に当たります


この正規表現を "お試しコードのテスト 第123回" に対して実行すると、全体がマッチします。
一回だけ見つけられるので、matches の要素数は 1 で、そのひとつ目の Match では、

ここで、正規表現に () でくくった "(.+)" があるので、そこに一致する部分が SubMatches コレクションで取得できます。
() でくくった表現はひとつしかないので、SubMatches の要素数は1です。
そのひとつ目の内容は、文字列の先頭から、空白に続く「第」の前までが該当するので、
matches(0).SubMatches(0) は "お試しコードのテスト" になります。


もし複数の条件を追加しようとする場合は
「Set re」の部分を「re1」「re2」「re3」として
同じような処理を回すみたいなのが一番効率がいいのでしょうか
ちなみに追加したいのは以下です。


・第XX話
・#XX
・(XX)
・(XX)
・XX話

※スペースの条件も1つ目と同じです。
※XXは数字で大文字も含む

「数字で大文字」というのは、全角のことですよね。
こんな感じになります。

Sub re_test (data, re)
 Set matches = re.Execute(data)
 result = matches(0).SubMatches(0)  ' これが "テスト" になってます
 WScript.echo "'" & result & "' <-- '" & data & "'"
end sub

Set re = new RegExp
re.Pattern = "^([^  ]+)[  ]+[第#((]?[0-90-9]+[回話))]?"

re_test "お試しコードのテスト 第123話" , re
re_test "お試しコードのテスト #123 あああ" , re
re_test "お試しコードのテスト  (123)" , re
re_test "お試しコードのテスト (123)" , re
re_test "お試しコードのテスト 123話" , re
re_test "お試しコードのテスト 第456話" , re
re_test "お試しコードのテスト #456 あああ" , re
re_test "お試しコードのテスト  (456)" , re
re_test "お試しコードのテスト (456)" , re
re_test "お試しコードのテスト 456話" , re

正規表現を変えたのと、動作確認の部分をサブルーチンにしただけです。

追加された条件と合わせて考えると、数字の部分と、その前後に一文字付くかもしれない、ということになります。

数字の部分には、全角も含むということなので、[0-90-9]+ としました。

数字の前に付く文字は、四つあって、そのうちのどれかということで [第#((]? です。
"?" は、直前の表現が0回か1回、という意味です。
"第?" で、第がひとつ付くか、付かないか、という意味で、これを [ ] で複数指定してます。

数字の後に付く文字も、同様に [回話))]? としてます。


gocnia3さんのコメント
はやい! ありがとうございます! まだ動かしてないのですが、勉強がてらした3行が何をやってるか教えていただくと幸いです(ぐーぐる先生に聞いてみましたがどうもよくわからない。。) >re.Global = True >Set matches = re.Execute(data) >result = matches(0).SubMatches(0) ' これが "テスト" になってます とりあえず明日にでも動かしながら動作の確認もしてみます!

gocnia3さんのコメント
ありがとうございます! 理解できました。詳細な解説に感謝いたします! 動かしてみますね あともう一点ずうずうしいながらお伺いしたいのですが、 現在は「お試しコードのテスト 第123回」を「お試しコードのテスト」にする という1つの条件だったのですが、 もし複数の条件を追加しようとする場合は 「Set re」の部分を「re1」「re2」「re3」として 同じような処理を回すみたいなのが一番効率がいいのでしょうか ちなみに追加したいのは以下です。 ・第XX話 ・#XX ・(XX) ・(XX) ・XX話 ※スペースの条件も1つ目と同じです。 ※XXは数字で大文字も含む

a-kuma3さんのコメント
>> もし複数の条件を追加しようとする場合は << 条件によりますが、正規表現をひとつにまとめられるなら、それが一番効率が良いです。 試した結果は、回答の方に追記します。

gocnia3さんのコメント
ありがとうございます。 まだ動かせてないですが(場所が場所で。。) ご丁寧にご回答頂き、感謝いたします!

gocnia3さんのコメント
すみません。 最後にもう一度教えてください。 以下の場合、今までの正規表現ですと、「#6」が削除され「お試しコードのテスト TEST2「テストメッセージ」」 となりますが、さらに「」とその中の文字も含めて削除したい場合は、新たにもう一度条件を追加(おそらく?『"^(.+)[ ]*[.+]"』) して新たに処理をさせる方法でしょうか?若しくは正規表現をひとつにまとめられる方法がありますでしょうか ■実行前【お試しコードのテスト TESTX「テストメッセージ」#6】 ■実行後(今まで)【お試しコードのテスト TESTX「テストメッセージ」】 ■今回(これにしたい)【お試しコードのテスト TESTX】 ■実行前【お試しコードのテスト テストX「テストメッセージ」#6】 ■実行後(今まで)【お試しコードのテスト テストX「テストメッセージ」】 ■今回(これにしたい)【お試しコードのテスト テストX】

gocnia3さんのコメント
『"^(.+)[ ]*[.+]"』じゃなくて 『"^(.+)[ ]*[「((]+.+[」))]"』でしたね(プラス『()』と『()』を追加しました。)

a-kuma3さんのコメント
>> 最後にもう一度教えてください。 << 300pt も、もらっちゃったら、断れないじゃないですかー(嘘 今まで回答に書いてたのは、間に空白があるのを前提にしてたので、このままでは、ちょっとやりずらいです。 がらっと方針を変えて、「置き換える」方式に変えました。 windofjuly さんのとは違って、文字列の末尾を空文字列で置き換えてます。 >|vb| Sub re_test (data, re) result = re.Replace(data, "") WScript.echo "'" & result & "' <-- '" & data & "'" end sub Set re = new RegExp re.Pattern = "[ ]*(「[^」]+」)?[第#((]?[0-90-9]+[回話))]?.*" re_test "お試しコードのテスト 第123話" , re re_test "お試しコードのテスト #123 あああ" , re re_test "お試しコードのテスト (123)" , re re_test "お試しコードのテスト (123)" , re re_test "お試しコードのテスト 123話" , re re_test "お試しコードのテスト 第456話" , re re_test "お試しコードのテスト #456 あああ" , re re_test "お試しコードのテスト (456)" , re re_test "お試しコードのテスト (456)" , re re_test "お試しコードのテスト 456話" , re re_test "お試しコードのテスト TESTX「テストメッセージ」#6" , re re_test "お試しコードのテスト テストX「テストメッセージ」#6" , re ||< 正規表現からは、残したい文字列に相当する表現が消え、 RegExp のメソッドも、Execute から Replace に変えてます。

gocnia3さんのコメント
本当にありがとうございます なんならお金を手渡したいぐらいです笑 頑張って正規表現を読んでみたのですが ちなみに今の正規表現の場合、いかみたいなのが来たらやっぱりマッチしちゃうんですよね(動かしてないのにスミマセン。。) >re_test "お試しコードのテスト 456" , re

a-kuma3さんのコメント
>> ちなみに今の正規表現の場合、いかみたいなのが来たらやっぱりマッチしちゃうんですよね(動かしてないのにスミマセン。。) << というのは、456を削って<span style="color:red;">欲しくない</span> ということ?

gocnia3さんのコメント
回答遅れまして申し訳ございません。(通知されない。。設定がおかしいのかな) 条件として、『#』が前についた場合のみに限定したいんです。

a-kuma3さんのコメント
「#」以外の、「第?話」とか「?話」の条件を残したままで、ってことですよね。

gocnia3さんのコメント
そうなんですよ。

a-kuma3さんのコメント
考え方を変えました。 微妙なパターンが多いので、それぞれを "|" でくっつけます。 対応してるのは、以下の六つ。 -第?回 -第?話 -#? -(?) -(?) -?話 これの前に「...」があれば削除。更に前に空白(含む、全角空白)を削除。 >|vb| Sub re_test (data, re) result = re.Replace(data, "") WScript.echo "'" & result & "' <-- '" & data & "'" end sub Set re = new RegExp 're.Pattern = "[ ]*(「[^」]+」)?[第#((]?[0-90-9]+[回話))]?.*" re.Pattern = "[ ]*(「[^」]+」)?(第[0-90-9]+回|第[0-90-9]+話|#[0-90-9]+|\([0-90-9]+\)|([0-90-9]+)|[0-90-9]+話).*$" re_test "お試しコードのテスト 第123話" , re re_test "お試しコードのテスト #123 あああ" , re re_test "お試しコードのテスト (123)" , re re_test "お試しコードのテスト (123)" , re re_test "お試しコードのテスト 123話" , re re_test "お試しコードのテスト 第456話" , re re_test "お試しコードのテスト #456 あああ" , re re_test "お試しコードのテスト (456)" , re re_test "お試しコードのテスト (456)" , re re_test "お試しコードのテスト 456話" , re re_test "お試しコードのテスト 456" , re re_test "お試しコードのテスト TESTX「テストメッセージ」#6" , re re_test "お試しコードのテスト テストX「テストメッセージ」#6" , re ||< 実行結果。 >|txt| 'お試しコードのテスト' <-- 'お試しコードのテスト 第123話' 'お試しコードのテスト' <-- 'お試しコードのテスト #123 あああ' 'お試しコードのテスト' <-- 'お試しコードのテスト (123)' 'お試しコードのテスト' <-- 'お試しコードのテスト (123)' 'お試しコードのテスト' <-- 'お試しコードのテスト 123話' 'お試しコードのテスト' <-- 'お試しコードのテスト 第456話' 'お試しコードのテスト' <-- 'お試しコードのテスト #456 あああ' 'お試しコードのテスト' <-- 'お試しコードのテスト (456)' 'お試しコードのテスト' <-- 'お試しコードのテスト (456)' 'お試しコードのテスト' <-- 'お試しコードのテスト 456話' 'お試しコードのテスト 456' <-- 'お試しコードのテスト 456' 'お試しコードのテスト TESTX' <-- 'お試しコードのテスト TESTX「テストメッセージ」#6' 'お試しコードのテスト テストX' <-- 'お試しコードのテスト テストX「テストメッセージ」#6' ||<

gocnia3さんのコメント
すみません!連絡遅れました 最初の質問からだいぶ複雑化しても何度もお答えいただきありがとうございました! 僕もa-kuma3並にかけるように勉強しなければですね まずは本を一通りやるか… ありがとうございました!

2 ● うぃんど
●40ポイント

正規表現を使います
vbsなら下記のような具合です

Option Explicit

' データ準備
Dim s1, s2
s1 = "テスト 第195回  "
s2 = ""

' 正規表現による置換
Dim r
Set r = New RegExp
r.Pattern = "(.*)[  ]*第[0-90-9]+回.*"
s2 = r.Replace(s1, "$1")

' 結果出力
WScript.Echo "[" & s2 & "]"

前後の空白を消せたかどうかの確認のため、結果出力では[角括弧]でくくってます


a-kuma3さんのコメント
あ、VBA じゃなくて、VBScript だったか ><

gocnia3さんのコメント
これも勉強になります! 正直初心者過ぎていろんなコードを見れてうれしいです

うぃんどさんのコメント
a-kuma3 さんのは、 必要な部分だけを抜き出す手法です 私のは、 不要な部分を消し去るという手法です Microsoftのデベロッパー向けのサイトに解説があるので読んでみると良いでしょう http://msdn.microsoft.com/ja-jp/library/ms974570.aspx

gocnia3さんのコメント
なるほど。実はぐーぐる先生にその頁をおしえてもらったのですが理解できませんでした。やはり自分でがりがりやんないとわからないままですね。。 ご回答ありがとうございました。

3 ● oil999
●20ポイント

スクリプトを組んでみました。
元の文字列を変数sourに入れると、変数destに切り出したい文字列が入るようになっています。
もし元の文字列がルール通りでないと、destは空になります。

Option Explicit

Dim sour, dest
Dim re, remat

sour = "テスト  第123回"  '元の文字列

'正規表現パターンの設定
Set re = new RegExp
re.IgnoreCase = True
re.Global = True
re.pattern = "^(.+)([  ]+第[0-9]{1,3}回)$"
Set remat = re.Execute(sour)

'抽出
dest = ""
if (remat.Count = 1) Then
 dest = remat(0).SubMatches(0)
End If

Set re = Nothing

MsgBox dest  '表示

gocnia3さんのコメント
ご回答に感謝いたします。勉強になります
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ