質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Q&A

解決済

2回答

5637閲覧

GASにて文章から特定の文字を抽出する方法

fuku-chann

総合スコア82

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

0グッド

1クリップ

投稿2020/05/04 16:01

編集2020/05/07 00:52

いつもお世話になっております。
GASでスプレッドシートに特定のGmailを取得させています。

文章から特定の文字を抽出していますが、検索条件に「(」を入れるとエラーになります。(下記文章の日付と時間だけを抽出したいです。「04/28/2020 08:30-11:00」)

おそらく量指定子だからと推測していますが、「(」にしても同様のエラーがでてしまいます。

この場合、どのようにしたらよいでしょうか?

【文章】

When you send the email, the reservation will be finalized.

Appointments:

  • 04/28/2020 08:30-11:00 (+ USB port expansion)

Name: ふく

Phone number: 090-8765-4321

【参考にした記事】
サルにもわかる正規表現入門
2.正規表現で使用する特殊文字
メタ文字を単なる普通の文字として検索したい場合は、それらメタ文字の前に、\を付加しなければなりません。

GAS

1function contact_Gmail() { 2 var rowNumber = 2; 3 var mysheetname = 'Gmail解析_' + Utilities.formatDate(new Date(), 'JST', 'yyyyMMddHHmmss'); 4 5 var GmailSS = SpreadsheetApp.create(mysheetname); 6 var mySheet = GmailSS.getSheets()[0]; 7 mySheet.setName(mysheetname); 8 mySheet.getRange(1,1).setValue("日時"); 9 mySheet.getRange(1,2).setValue("送信元"); 10 mySheet.getRange(1,3).setValue("件名"); 11 mySheet.getRange(1,4).setValue("本文"); 12 mySheet.getRange(1,5).setValue("ご予約"); 13 mySheet.getRange(1,6).setValue("お名前"); 14 mySheet.getRange(1,7).setValue("電話番号"); 15 mySheet.getRange(1,8).setValue("メールアドレス"); 16 17 var newfolder = DriveApp.createFolder(mysheetname); 18 19 var searchQuery = 'subject:("finalized") '; 20 var threads = GmailApp.search(searchQuery, 0, 200); 21 22 var mymsg=[]; 23 24 var msgs = GmailApp.getMessagesForThreads(threads); 25 26 for(var i = 0; i < msgs.length; i++) { 27 mymsg[i]=[]; 28 for(var j = 0; j < msgs[i].length; j++) { 29 mymsg[i][0] = msgs[i][j].getDate(); 30 mymsg[i][1] = msgs[i][j].getFrom(); 31 mymsg[i][2] = msgs[i][j].getSubject(); 32 var nbsp = String.fromCharCode(160); 33 mymsg[i][3] = msgs[i][j].getPlainBody() 34 mymsg[i][4] = fetchData(mymsg[i][3],'Appointments: -','(').replace(/\s+/g, ""); 35 } 36 } 37 if(mymsg.length>0){ 38 GmailSS.getSheets()[0].getRange(2, 1, i, 5).setValues(mymsg); //シートに貼り付け 39 } 40} 41//'[^"]+' 42function fetchData(str, pre, suf) { 43 var reg = new RegExp(pre + '.*?' + suf,'s'); 44 var data = str.match(reg)[0] 45 .replace(pre, '') 46 .replace(suf, ''); 47 return data; 48}

20200505 9:55 コード修正しました。(Appointmentsの最後のsが抜けていたので修正しました。)
mymsg[i][4] = fetchData(mymsg[i][3],'Appointments: -','(').replace(/\s+/g, "");

20200506 9:02 VScodeの画面のスクリーンショットを追加しました。
vsCode

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

draq

2020/05/04 19:09

前も書いた気がしますが、エラーになります、じゃわかりません。どんなエラーが、どこででるのかを書いてください。 あと、毎回ソース全体を提示して質問されていますが、もっと他の人に再現可能な最小コードでテストされた方がいいです。今回であれば、入力文字列と検索文字列をパラメータとして使用し何を得たいのかを考えたコードを作成して見てください。
fuku-chann

2020/05/05 00:15

draq様 ご指摘ありがとうございます。 下記のエラーが出ています。(掲載するの忘れていました。すみません。。。) SyntaxError: Invalid regular expression: /Appointments:.*?(/: Unterminated group(行 43、ファイル「コード」) コードの件、トライしてみます。(私には少し難題ですが;)
oikashinoa

2020/05/05 00:31

エラーの内容は理解してます?理解してると何を直せば良いか分かるので楽になりますよ。 SyntaxError: Invalid regular expression: あと、エラーの行数だけ書かれても…複数の他人に44行目を探させます?少しの気遣いで回答者が増えますよ。
oikashinoa

2020/05/05 00:39

draqさんも書いているように乗せるソースも今問題が起きているソースを、関係している部分だけにして乗せると良いですよ。 最小限にする過程で、自分でおかしい箇所を見つけることが多々あります。 また、他の人にも見てもらいやすくなり回答受けやすくなります。 面倒くさいようですがメリットが大きいです。
oikashinoa

2020/05/05 00:48

最後に。 載せるソースば正確に。 以下の部分直したのならその旨を本文にでも書くべきです。 古いソースで回答しようとしてましたので… mymsg[i][4] = fetchData(mymsg[i][3],'Appointments: -'
fuku-chann

2020/05/05 00:51

oikashinoa様 ご回答ありがとうございます。 不手際がありすみません。 エラー内容はあまり理解できていないと思います。 エラーは直訳すると、正規表現が有効ではないという意味だと思いますが、検索ワード('-','\(')が量指定子(.*? ,s)に対応されていないということではないでしょうか? 行番号追記致しますm_ _m 43行目:var reg = new RegExp(pre + '.*?' + suf,'s'); 44行目:var data = str.match(reg)[0]
guest

回答2

0

ベストアンサー

最小限のコードは以下のような感じになるかと。
関係ないコードを出来るだけ省いていきます。

  • 確認したいコードがある関数を残す
  • その関数への引数は予め準備して作っておく

こうしておけばGAS/スプレッドシートが使えない人からも回答もらいやすいですよね?
また、整理する段階で問題に気づくことも多々有ります。(自己解決してしまう)

js

1const str = `When you send the email, the reservation will be finalized. 2 3Appointments: 4 504/28/2020 08:30-11:00 (+ USB port expansion) 6Name: ふく 7 8Phone number: 090-8765-4321`; //セミコロンでは無く、バッククォートで囲ってあります 9// 04/28/2020の前に - が入るのか…質問本文からは判断つきませんので直して下さい。 10 11function fetchData(str, pre, suf) { 12 console.log('pre + .*? + suf', pre + '.*?' + suf); //引数の内容は想定通りですか? 13 var reg = new RegExp(pre + '.*?' + suf, 's'); 14 var data = str.match(reg) 15 return data; 16}; 17 18console.log(fetchData(str,'Appointments: -','(').replace(/\s+/g, "")); 19 20
  1. //で書いてあるコメントを確認して下さい
  2. function fetchDataの下に、 console.logを追加しました。

まずは引数が想定通りか考えてみましょう


  1. //で書いて(略)… の誤字を修正しました

投稿2020/05/05 01:31

編集2020/05/05 02:16
oikashinoa

総合スコア2826

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oikashinoa

2020/05/05 05:43 編集

ヒント 1. SyntaxError: Invalid regular expression: /Appointments:.*?(/: Unterminated group(行 43、ファイル「コード」) Unterminated group の意味も調べてみましょう 2. 自身が参考にした記事の内容と、⇡console.log()の喧嘩で想定外のことが起きてませんか? > 【参考にした記事】 > 2.正規表現で使用する特殊文字 > メタ文字を単なる普通の文字として検索したい場合は、それらメタ文字の前に、\を付加しなければなりません。
fuku-chann

2020/05/05 06:11

oikashinoa様 ご回答ありがとうございます。 1.unterminated groupはバックスラッシュでエスケープする必要があると記載されていました。 You should escape (, {, } and . with \: https://stackoverflow.com/questions/28187300/unterminated-group-in-regexp 2は正直付いていけていません。作成頂いたコードはどのように使えばいいのでしょうか?(せっかく作成頂いたのにすみません。。。)
oikashinoa

2020/05/05 06:40

スマホからなので簡単に。 1は、想定外のことが起きたことで発生している問題です。(今の理解レベルなら2を先に解決しましょう) 2は、使う正規表現がどこかおかしい所があるか確認するためのコードです。 pre + '.*?' + sufの内容が想定どおりですか?
fuku-chann

2020/05/05 06:54

oikashinoa様 ご回答ありがとうございます。 作成頂いたコードをGASで読み込むと下記のエラーが発生してしまいます; SyntaxError: Invalid regular expression: /Appointments: -.*?(/: Unterminated group(行 13、ファイル「コード」) 13行:var reg = new RegExp(pre + '.*?' + suf, 's'); 引数の内容を確認できない状態です。。。
fuku-chann

2020/05/05 07:58 編集

oikashinoa様 ご回答ありがとうございます。 2か所をLogger.logに変更しましたが、同様のエラーが発生しています。 SyntaxError: Invalid regular expression: /Appointments: -.*?(/: Unterminated group(行 13、ファイル「コード」) そのため、内容が確認できない状況です。(たびたびお手数をおかけしております)
oikashinoa

2020/05/05 08:53

スマホからなので簡単に。時間がなくなってきた… pre + '.*?' + sufの結果は以下となります Appointments: -.*?(
oikashinoa

2020/05/05 09:09 編集

想定は以下の行から考えると… mymsg[i][4] = fetchData(mymsg[i][3],'Appointments: -','(').replace(/\s+/g, ""); _____________________________________________^^^^ Appointments: -.*?( にしたいのでは? (の前に\が有る状態 以下を読んで下さい。どのように修正すればよいか分かるでしょう [RegExp - JavaScript | MDN] - https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp > 解説 (略) > コンストラクタ関数を使用する場合は、通常の文字エスケープ規則 (文字列内に特殊文字が含まれるとき、前に \ を付加する) が必須です。例えば、以下 2 つの構文は同等です: > var re = /\w+/; > var re = new RegExp('\w+');
fuku-chann

2020/05/05 09:40 編集

oikawashinoa様 ご回答ありがとうございます。 なかなか理解できず時間を取らせてしまいすみません。 バックスラッシュを2つ使うことでエラーが解除されました。 mymsg[i][4] = fetchData(mymsg[i][3],'Appointments:-','\('); 取得した文末に(がついてしまいました; 取得された文章:04/28/202008:30-11:00(
oikashinoa

2020/05/05 13:02

以下の部分のsufの中身がnew RegExp()用の内容”//(”になっているのに、 .replace(suf, '')を動かすからですよ。 ”//(”なんて文字列は無いので消せない function fetchData(str, pre, suf) { var reg = new RegExp(pre + '.*?' + suf,'s'); var data = str.match(reg)[0] .replace(pre, '') .replace(suf, ''); ^^^^^^^^^^^^^ -> .replace(new RegExp(suf), ''); return data; } .replace(new RegExp(suf), ''); とするか、そもそもの正規表現を変えたほうがスムーズかと。
fuku-chann

2020/05/05 13:49

oikashinoa様 ご回答ありがとうございます。 .replace(new RegExp(suf), '');で取得したい文字列が得られました。 ありがとうございました。
guest

0

正規表現を変えたパターンなので別回答です。
…正規表現は上手ではないのでもっと方法が有るかもです。

直接、日時の文字列を指定します。

js

1const str = `When you send the email, the reservation will be finalized. 2 3Appointments: 4 5ゴミデータ 61/2/2020 3:44-5:6 (+ USB port expansion) 7 8 9Name: ふく04/28/2020 02:30-11:00 (ダミーデータ) 10 11Phone number: 090-8765-4321`; //セミコロンでは無く、バッククォートで囲ってあります 12 13//余計なものまで拾うNGパターン 14var sample1 = str.match(new RegExp(/\d{1,2}/\d{1,2}/\d{1,4}\s+\d{1,2}\:\d{1,2}\-\d{1,2}\:\d{1,2}/, "g")); 15console.log('sample1', sample1); // sample1 [ '1/2/2020 3:44-5:6', '04/28/2020 02:30-11:00' ] 16 17//Appointments: 〜 日時フォーマット 〜 スペース以降全て の内、日時フォーマット 18var sample2 = str.match(new RegExp(/^.*Appointments:\s*.*?(\d{1,2}/\d{1,2}/\d{1,4}\s+\d{1,2}\:\d{1,2}\-\d{1,2}\:\d{1,2})\s*.*/, "s"))[1]; 19console.log('sample2', sample2); // sample2 1/2/2020 3:44-5:6 20 21//Appointments: 〜 日フォーマット、時フォーマット 〜 スペース以降全て の内、日フォーマットと時フォーマットを分ける 22var sample3 = str.match(new RegExp(/^.*Appointments:\s*.*?(\d{1,2}/\d{1,2}/\d{1,4})\s+(\d{1,2}\:\d{1,2}\-\d{1,2}\:\d{1,2})\s*.*/,"s")); 23const [date, time] = [sample3[1], sample3[2]]; //V8ランタイムにしたら、分割代入可能‥なハズ 24console.log('sample3',date, time); // sample3 1/2/2020 3:44-5:6 25 26

\d{1,2}など見慣れないものは一度調べてみて下さい。
正規表現 - JavaScript | MDN


2020-05-06 00:22:36 追記

GASのランタイムをRhino→V8に換える必要が有るかもしれませんので以下を見て下さい。

v8に換える前提で、sample3は分割代入を使用しました。

投稿2020/05/05 14:29

編集2020/05/05 15:23
oikashinoa

総合スコア2826

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuku-chann

2020/05/05 15:08

oikashinoa様 ご回答ありがとうございます。 正規表現バージョンまで作成頂けるとは思っておりませんでした。 感激しました。 実はこちらのコード使いこなせておりません。 GASだと使えないようですので、VScodeやatomで使うことができるのでしょうか?
oikashinoa

2020/05/05 15:24 編集

GASのランタイムをRhino→V8に換える必要が有るかもしれませんので、色々本文に追記しました。 私はVS Codeで動かしてます。ので、GASで動くかは確認できてません…がたぶん動くと思います。
fuku-chann

2020/05/05 15:34

oikashinoa様 ご回答ありがとうございます。 ランチタイムは元々有効になっていましたが、ダメでした。。。 VS Codeの場合、コードをコピペしてそのあとどうすればいいのでしょうか? (脱線するので別の質問をしたほうが良いでしょうか?)
oikashinoa

2020/05/05 15:50 編集

CodePenでも動いたけど、GASではNGなんですかね…ごめんなさい。GASは未検証です で、機能拡張は以下を使っています。Quokka.jsはおすすめ。 [Quokka.js - Visual Studio Marketplace] - https://marketplace.visualstudio.com/items?itemName=WallabyJs.quokka-vscode 無料版でも十分。私は感謝の意味を込めてお布施してます。手放せません。 何故流行らないのか不思議。 [Node.js REPL - Visual Studio Marketplace] - https://marketplace.visualstudio.com/items?itemName=lostfields.nodejs-repl まだ開発中…
fuku-chann

2020/05/06 00:01

oikashinoa様 ご回答ありがとうございます。 Quokka.jsインストールしました。 どのような画面になればよいのでしょうか? 画面スクリーンショット取ったのでお時間あるときにご確認お願いします。
oikashinoa

2020/05/06 00:12

1.言語モードをJavaScriptにする必要が有ります。 2.コマンドパレットで、quokka.jsを起動してください。 [VSCodeのJavaScript用拡張機能Quokkaが便利 - 背筋を伸ばしてスタートアップするブログ] - https://katsuki.hatenablog.com/entry/2018/11/24/181601 慣れてきたら、本家の資料も見たほうがいいです。英語ですけど動画も有るのでわかりやすいです https://quokkajs.com/docs/
oikashinoa

2020/05/06 01:58

IMEが有効になっていると、参考にされたHPに書いてあるショートカットキーが通らないことが有ります(Ubuntu/Linuxの場合) 本文に張ってある画面で言うと、右下に”JavaScript React”って書いてある部bンをクリックすると選択肢が出るのでそこで”JavaScript”を選んでみて下さい… そろそろVS Codeの話ばっかりになって来てるので、別質問にしたほうが良いですね。
fuku-chann

2020/05/06 02:11

oikashinoa様 ご回答ありがとうございます。 新しく質問いたしました。 もしよろしければお付き合いください。 https://teratail.com/questions/259187?modal=q-comp 本件大変お世話になりました。 とても勉強になりました。 ありがとうございました。
fuku-chann

2020/05/07 00:56

oikashinoa様 いつもお世話になっております。 昨日vsCodeのセットアップが終わり、作成頂いた正規表現のコンソールを確認することができました。 ありがとうございました。 あの正規表現は凄いですね。どうやったらあんな正規表現が作成できるのでしょうか。。。 今度正規表現について教えて欲しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問