現在VBScriptである特定の文字以降を削除する方法を考えております。
現在LEN関数などで、特定の文字以降を削除する方法はわかったのですが、
複数の条件を加えたところ、当方のスキルでは出来ない状態です。
以下の条件を満たせるサンプルスクリプトを作成いただけないでしょうか
■文字列操作内容
□文字列処理対象: 「テスト 第XX回」
□文字列処理後の姿: 「テスト」
※文字列処理対象内の「XX」は数字1から3桁の場合があります。
※文字列処理対象内の「第」の前のスペースは半角、全角を含みます。また複数のスペースがある場合も削除対象となります。
上記のように、文字列の中で「第」の後に「XX」という数字2桁(若しくは1桁)がきて、その次の文字が「回」だった場合に
「第」から後ろを削除するというものです。また削除する際に、「第」の前にスペースが存在した場合は
スペースも含め削除というものです。(スペースは半角、全角を含む。また複数のスペースがある場合も全て削除対象)
宜しくお願い致します。
こんな感じ。
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 に設定している文字列が正規表現です。
ちょっと分かりにくいですが、[ ] の中には、半角の空白と全角の空白が続けて書いてあります。
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回、という意味です。
"第?" で、第がひとつ付くか、付かないか、という意味で、これを [ ] で複数指定してます。
数字の後に付く文字も、同様に [回話))]? としてます。
こんな感じ。
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 に設定している文字列が正規表現です。
ちょっと分かりにくいですが、[ ] の中には、半角の空白と全角の空白が続けて書いてあります。
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回、という意味です。
"第?" で、第がひとつ付くか、付かないか、という意味で、これを [ ] で複数指定してます。
数字の後に付く文字も、同様に [回話))]? としてます。
考え方を変えました。
微妙なパターンが多いので、それぞれを "|" でくっつけます。
対応してるのは、以下の六つ。
これの前に「...」があれば削除。更に前に空白(含む、全角空白)を削除。
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
実行結果。
'お試しコードのテスト' <-- 'お試しコードのテスト 第123話' 'お試しコードのテスト' <-- 'お試しコードのテスト #123 あああ' 'お試しコードのテスト' <-- 'お試しコードのテスト (123)' 'お試しコードのテスト' <-- 'お試しコードのテスト (123)' 'お試しコードのテスト' <-- 'お試しコードのテスト 123話' 'お試しコードのテスト' <-- 'お試しコードのテスト 第456話' 'お試しコードのテスト' <-- 'お試しコードのテスト #456 あああ' 'お試しコードのテスト' <-- 'お試しコードのテスト (456)' 'お試しコードのテスト' <-- 'お試しコードのテスト (456)' 'お試しコードのテスト' <-- 'お試しコードのテスト 456話' 'お試しコードのテスト 456' <-- 'お試しコードのテスト 456' 'お試しコードのテスト TESTX' <-- 'お試しコードのテスト TESTX「テストメッセージ」#6' 'お試しコードのテスト テストX' <-- 'お試しコードのテスト テストX「テストメッセージ」#6'
すみません!連絡遅れました
最初の質問からだいぶ複雑化しても何度もお答えいただきありがとうございました!
僕もa-kuma3並にかけるように勉強しなければですね
まずは本を一通りやるか…
ありがとうございました!
正規表現を使います
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 さんのは、
必要な部分だけを抜き出す手法です
私のは、
不要な部分を消し去るという手法です
Microsoftのデベロッパー向けのサイトに解説があるので読んでみると良いでしょう
http://msdn.microsoft.com/ja-jp/library/ms974570.aspx
なるほど。実はぐーぐる先生にその頁をおしえてもらったのですが理解できませんでした。やはり自分でがりがりやんないとわからないままですね。。
ご回答ありがとうございました。
スクリプトを組んでみました。
元の文字列を変数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 '表示
ご回答に感謝いたします。勉強になります
考え方を変えました。
微妙なパターンが多いので、それぞれを "|" でくっつけます。
対応してるのは、以下の六つ。
これの前に「...」があれば削除。更に前に空白(含む、全角空白)を削除。
実行結果。
2012/02/02 16:06:09すみません!連絡遅れました
2012/02/07 21:35:11最初の質問からだいぶ複雑化しても何度もお答えいただきありがとうございました!
僕もa-kuma3並にかけるように勉強しなければですね
まずは本を一通りやるか…
ありがとうございました!