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

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

ただいまの
回答率

88.23%

正規表現で括弧以外のアルファベットだけ置換えしたい

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 970

gpioblink

score 12

動画の英語字幕があります。
この英語字幕の一部を伏せ字にしてタイピングゲームを作ろうとしています。

str.replace(/[A-Za-z]/g, '_')で字幕のアルファベット部分を伏せ字にしていたのですが、問題が発生しました。

このキャプションには、「(動作音)」や「[人名]」など会話以外の内容が括弧にくくられて入っています。
この部分は実際に動画で発音していないので、伏せ字にしたくありません。

括弧内以外のアルファベットにヒットする正規表現を教えてください!

入力例

-[TOM] ♪ Taking care to keep my baggage with me ♪
-(banging) Huh?


よくない出力

-[___] ♪ ______ ____ __ ____ __ _______ ____ __ ♪
-(_______) ___?


期待する出力

-[TOM] ♪ ______ ____ __ ____ __ _______ ____ __ ♪
-(banging) ___?
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+3

String.prototype.replace

括弧内以外のアルファベットにヒットする正規表現を教えてください!

正規表現は一度、マッチした文字列には二度とマッチしません
括弧全体にマッチさせてから、マッチした文字列をそのまま返す置換処理にしてください。

'use strict';
const string = '-[TOM] ♪ Taking care to keep my baggage with me ♪\n-(banging) Huh?';
const result = string.replace(/\([^)]*\)|\[[^\]]*\]|([a-zA-Z])/g, function callbackfn (match, alphabet) {
  return alphabet ? '_' : match;
});

console.log(result);  // "-[TOM] ♪ ______ ____ __ ____ __ _______ ____ __ ♪\n-(banging) ___?"

丸投げ質問

 コードをください・デバッグしてください等の丸投げの質問

何かを作りたいのでコードを書いてほしい、学校の課題を解いてほしい等の質問は、具体的にプログラミングで困っている質問ではないと考え、推奨していません。
問題や質問は実際に調査や作業に取り組み、具体的なところで生まれると考えるためです。
まずは実際に作業に取り組み、つまづいたところで投稿をしてみてください。

この状況で打開策に悩む気持ちは理解できるので、答えを書きましたが、丸投げ質問は推奨されません。

Re: gpioblink さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 14:51

    回答ありがとうございます!replaceでも複数の引数をとって関数が使えるんですね。すいません、丸投げは気をつけます。

    キャンセル

  • 2019/01/13 15:29

    [] の例外処理に対応しておきました。

    キャンセル

+1

正規表現の密林に迷い込むと簡単には抜けられなくなります。
なので、カッコ内の部分だけを記憶しておいて、あとで合体するというのはどうでしょう。

<div id="org">
-[TOM] ♪ Taking care to keep my baggage with me ♪<br>
-(banging) Huh?
</div>
<button onclick="change()">change</button>
<div id="changed"/>
function change(){
  var str=document.getElementById('org').innerText;
  var matchedlist=str.match(/[\(\[].*?[\)\]]/g);
  str=str.replace(/[\(\[].*?[\)\]]/g,'*');
  str=str.replace(/[A-z]/g,'_');
  var strarray=str.split('*');
  str='';
  for(var i=0,len=strarray.length;i<len;i++){
    str+=strarray[i];
    if(matchedlist[i]){
      str+=matchedlist[i]
    }
  }
  document.getElementById('changed').innerText=str
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 14:19

    回答ありがとうございます!仮の文字で置き換えるのか、、直感的にわかりやすいです!

    キャンセル

  • 2019/01/13 14:38

    @satocha さん
    一時的に他の文字列に置換する場合は、メタキャラクタとなる文字が含まれた場合を考慮する必要があります。
    このコードでは、'abc*xyz' や 'abc(*)xyz)' など、*が含まれた文字列で期待通りに動作しません。

    キャンセル

  • 2019/01/13 14:45

    > str=str.replace(/[A-z]/g,'_');

    この正規表現は、"[\\]^_`" にマッチしてしまいます。

    キャンセル

+1

こんにちは。

会話に出現する単語は、以下の条件を満たすものと考えられます。

  • 半角アルファベット1文字以上で構成される文字列で、
  • かつ、その文字列の直前にある文字は、アルファベットおよび([ のいずれでもない。
  • かつ、その文字列の直後にある文字は、アルファベットおよび)] のいずれでもない。

この条件に沿って、会話中の単語を、これを囲む左右の文字を含めた正規表現

/[^a-z\(\[][a-z]+[^a-z\)\]]/i

でマッチさせ、このマッチ部分に含まれるアルファベットを _ に変換するような関数
maskingWordsInSpeech(text)
を作りました。

const maskingWordsInSpeech = (text) => {
  let x = text;
  while(true) {
    const y = x.replace(/[^a-z\(\[][a-z]+[^a-z\)\]]/i, 
      str => str.replace(/[a-z]/ig, '_')
    );
    if (x == y) break;
    x = y;
  }
  return x;
};

以上、参考になれば幸いです。

追記

単語の後にくる文字までマッチさせなければ、whileで回したりせずに以下で済みました。

const maskingWordsInSpeech =
  (text) => text.replace(/[^a-z\[\(][a-z]+/ig, s => s.replace(/[a-z]/ig, '_'));

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 16:40 編集

    @gpioblink さん
    私の回答がそれなんですが…。まあ、自分で書いてみるのは良い事です。
    https://teratail.com/questions/168504#reply-251459

    キャンセル

  • 2019/01/13 16:49

    みなさんの回答がとても参考になって、正直、全ての回答をベストアンサーにしたいです。
    様々なコードの特徴まで指摘していただいたthink49さんを選んで、質問を閉じさせてもらいます!
    一番始めに回答いただいたsatochaさん、分かりやすい説明をしていただいたjun68yktさん、括弧内除外の方法を始めに教えてくださったotnさんもありがとうございました!!

    キャンセル

  • 2019/01/13 20:16

    @gpioblinkさん
    > 正直、全ての回答をベストアンサーにしたいです。
    私の回答を通じて当初のご質問に要件として明示されていないけれども、有り得る入力について考慮するきっかけにして頂けたようで、大変嬉しく思います。

    キャンセル

+1

一気に1つの正規表現でと言うのは無理です。
splitで、括弧内と括弧外によりわけて、括弧外だけreplaceします。

str = str.split( /(\[.*?\]|\(.*?\))/ ).map(
        function(s){
            if(s.match( /(\[.*?\]|\(.*?\))/ )){
                return s;
            }else{
                return s.replace(/[A-Za-z]/g,"_");
            }
        }
    ).join("");

括弧内を表す正規表現:/(\[.*?\]|\(.*?\))/。この正規表現でsplitする。

splitした配列の各要素について、括弧内ならそのまま、そうでなければreplaceするように、mapで制御する。

最後に配列をjoinして文字列に戻す。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 14:29

    回答ありがとうございます!先読みとか後読みとか考えて、挫折していました。これならシンプルでわかりやすいです!2重括弧とかにも対応できそうで、ありがたいです。

    キャンセル

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

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る