• 締切済み

正規表現での(範囲内での)範囲選択

はじめて質問させていただきます。 ![https://path/path2/sampletext](https://okwave.jp/2) [https://path/path3/sampletext](https://okwave.jp/3) のように、頭に! がついたりつかなかったりするMDのリンクテキストがたくさんあり、これを一括で処理したいのですが、上の二行で取得したい文字列は以下のとおりです。 [https://path/path2/ [https://path/path3/ 言葉に直すと、[ を始まりとして、] までの間の範囲内での、[ と / に挟まれた最長の文字列(挟んでいる記号 [ と/ を含む) いろいろと調べたのですが、途中の/が干渉したり、後半の()内の文字列が干渉したり、冒頭の ! が干渉したり、と行った具合でお手上げになりました。 知識不足で恐縮ですが、どなたかご教授いただけると幸いです。

みんなの回答

  • 4017B
  • ベストアンサー率73% (1306/1777)
回答No.2

「MDのリンクテキスト」ってもしかして「"MarkDown記法" によって記述されたテキスト」て意味ですか?これまたビックリ。 そういう事は先に言ってくれないと…て、そのまま「MDのリンクテキスト」でggたら普通に "MarkDown関連" の検索結果から上位表示されますね…もしかしてコレって公式の略記? うん、まあこういう二度手間三度手間を防ぎ、互いの齟齬を出来るだけ減らす意味でも、今後はIT技術系の話をする際には必ず略語は使わず常に正式表記のみで記述してくださいしろ(最初の1回目で互いの定義が通じてればそれ以降は可)。 という訳で翻訳コンニャクすると… + 手元に「MarkDown記法によって記述されたテキスト」がある(それが複数のファイルなのか、或いは1つの巨大なファイルなのかは言えない)。 + そのテキストには規則性が無く、雑多な記述の中にリンク文字列が含まれている(そのテキスト自体を見せる事はできない)。 + そのテキストの中から「リンクを抽出」したい。 + 使えるツールは「Visual Studio Code」のみである。 ~でOKですか?特に一番重要な点は「何を抽出したいか」になるんですが。質問文のママだと… [https://path/path2/ ~という風に記述されてますが本当にそれで大丈夫ですか?普通に考えると文頭の [ が余分な気がしますが…それにURL自体も / で途切れていて、このままだとリンクとしても流用できないですし…何もかもが中途半端に感じます。その辺の所を省略せずに過不足無く詳細に補足して貰えれば、より正解に近い回答を出せるかもしれません。 P.S. よく見返したら自分の前回答もちょっと勘違いしてたというか誤りがありました。フルパスを抽出するのでは無くて、URLの最後のディレクトリ階層で区切る必要があるみたいですね。なのでちょっと手直してすると… (\[[^\]]+\/)[^\/]*\](?:\([^()]+\)) ~上記の「マッチングパターン」で過不足無く、テキスト文章の中に雑多に紛れ込んだ「MDのリンク」を洗いざらい抽出して、質問者の当初の希望?に沿った形で吐き出せると思います。少なくともPHPでの正規表現(preg_match_all)では問題無く抽出する事ができました。 ざっと検索した感じだと、どうやら "Visual Studio Code" では特に「デリミタ」を考慮する必要が無いみたいなので。一般的な正規表現を用いるときみたいに、検索文字列内の / にエスケープ文字を付与させる必要が無いみたいですので。もうちょっと簡略化する事も出来るかもしれませんが、エスケープ文字自体はある分には特に影響は無いはずなので。これをそのまま "Visual Studio Code" での正規表現にコピペしても問題無く動作すると思います。 コレでダメならこちらとしもお手上げと言うか…ちょっとどうしたらイイのか検討もつかないので、後は自力でなんとかしてもらうしか無いですね。それでまた何かどこかで再質問する場合は、前述の注意事項をちょっと念頭に置いてから、冗長になっても良いので、自分自身の作業環境と自分がやりたい事を過不足無く最初に全部さらけ出す様にした方が、より多くの人から真摯な回答が貰えると思いますよ。

hamtak
質問者

補足

4017Bさま いろいろとご丁寧な説明をありがとうございました。 ただしく書き直します。 + 手元に「MarkDown記法によって記述されたテキスト」がある(1つのファイル内に下記の規則性で数百行ある)。 + そのテキスト群には規則性が2種あり、 ![●●●/●●●/●●●](●●●) [●●●/●●●/●●●](●●●) であります。 エクスクラメーション+ブラケット囲み+カッコ囲み あるいは ブラケット囲み+カッコ囲み のいずれかであり、ブラケット内に入るスラッシュの数は不規則です。 + そのテキストの中から以下の文字列を抽出したい。 [ を始まりとして、] までの間の範囲内での、[ と / に挟まれた最長の文字列(挟んでいる記号 [ と/ を含む) 冒頭の例文でいえば、 [https://path/path2/ [https://path/path3/ + 普段作業しているツールは「Visual Studio Code」あるいは正規表現検索置換が可能なテキストエディタである。 以上となります。 もしおわかりになるようでしたら、お願いいたします。 (このポストで教えていただいた正規表現ではVSCode上で思う形でのキャプチャになりませんでした)

  • 4017B
  • ベストアンサー率73% (1306/1777)
回答No.1

PHP(v7.4)で良いのであれば… $str = <<<END ![https://path/path2/sampletext](https://okwave.jp/2) [https://path/path3/sampletext](https://okwave.jp/3) [https://path/path4/sampletext](https://okwave.jp/4) END; $reg = '#^!?(\[https:/(?:/[^/]+)+)\].*#m'; $rep = '$1'.PHP_EOL; $re = preg_replace( $reg, $rep, $str ); echo $re; ~みたいな感じでまあまあイイ感じに取ってくれるはず。ただし全対応にはなっていないので、入力文字列に ]] みたいな連続するモノがあると変になります。 他の環境でやる場合でも正規表現のためのマッチングパターンは割とそのままで流用可能なので、その場合はデリミタとスラッシュだけ適当に最適化してください。

hamtak
質問者

お礼

ありがとうございます! 私の説明が足りず失礼しました。 作業は、VSCode 上でテキストファイルの検索置換をしたい形でして、[のあとが必ずしもhttps://ということではなく。。という感じでした。 ご教授ありがとうございました。

関連するQ&A

  • (秀丸)正規表現で、特定文字列含む<~>範囲を選択

    お世話になります。 (秀丸の)正規表現について教えてください。 たとえば、テキストファイルに、1行、 ”<abc>文字列1です><abc>文字列2です><abc>文字列3です>(ここで改行)” という文字列が存在しています。 それを対象として、 (秀丸の)正規表現を利用し、 ”<abc>文字列2です>”だけをマッチさせたいのですが、 試しに、(秀丸の)正規表現で、 <abc.*文字列2.*?>  ←(なお、実際の記号は半角(.*?等)で、それぞれ入力しています・・・) で検索実行したところ、 ”<abc>文字列1です><abc>文字列2です>” として、 前の方に、マッチして欲しくない、 ”<abc>文字列1です>” までがマッチしてしまっている状況です。 そこでご質問なのですが、 上記におきまして、(秀丸の)正規表現を利用して、 ”<abc>文字列2です>”だけをマッチさせるには、 どのようにすれば、よろしかったでしょうか? (ちなみに秀丸は、2013年12月10日(火)現在の  最新バージョンVer8.32を利用しています) 以上になります。 宜しくお願いいたします。

  • 正規表現

    正規表現で 数値と半角記号(!#$%()~|-^@[;],./`{+*}_)が入っているというものを表現したいのですが、、、 下記のような正規表現をすると、エラーになってしまいます。何かよい方法はありませんか? ^[a-zA-Z0-9\-_!#$%()~|-^@[;],./`{+*}_]*$ 又、携帯電話のチェックをしたいのですが、 1文字以上の文字列があってというような処理にしたいのですが、何かよい方法はないでしょうか? ereg( "@docomo\.ne\.jp$", $email )

    • ベストアンサー
    • PHP
  • java正規表現について

    bufferdreaderで読み込んだファイルを1行ずつ読み込みます。そして、arraylistに追加していきます。そして、各行に”JP”という文字列があれば、表示しないプログラムを作りたいです。 (".*JP.*")だとうまくいきません… ちなみに、文頭、文末、文中どこでも検索できるようにしたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 【正規表現】コメントアウトされていない文字列のマッチ

    お世話になっております。 あるファイル群にgrepをかけて結果を取得したいのですが あと半歩という所でつまづいています。 正規表現の考え方のご示唆をいただけませんでしょうか。 宜しくお願い致します。 ■やりたいこと コメントアウトされていない文字列のマッチ ■対象文字列 1行目:ほげ 2行目://ほげ 3行目:// これは否定 ほげ 4行目:ほげ //ここにコメントがはいるとひっかからない(><) ■コメントアウト文字 // 1行目と4行目の「ほげ」をマッチさせたいのです。 正規表現の先読み否定を使って ^(?!//.*)ほげ$ 行頭から、「//」が後に続かなくて「ほげ」がある行末 とやってるのですが、 4行目がひっかかりません。 (?!//.*)の部分で、「//」から「ほげ」までを否定している為だと思うのですが、どのように考え、どのように記載すればスマートでしょうか。 お忙しい所恐縮ですが アドバイスいただければ幸いです。 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 正規表現にマッチする文字列の一括出力

    任意の正規表現を与えてやり、そのパターンに合致する文字列を 1行1文字列でテキストファイルに一括出力したいと考えています。 例えば、 [a-z][a-z][a-z] を与えてやると、 aaa aab aac aad ... ... zzx zzy zzz と、26の3乗で17576行の文字列をテキストファイルなどに出力。 LINUXのコマンドラインなら多少分かるのですが、プログラミングは さっぱりで、上記の目的につかえそうなユーティリティも探してみた のですが、見つけることはできませんでした。 よい方法がありましたら、ご教授よろしくお願いいたします。

  • 正規表現のタイプがわからない(初心者)

    正規表現で置換ができることを知り、こういうサイトを見つけました。 @IT:Windows TIPS -- Tips:複数ファイルの文字列置換をワンクリックで行なう http://www.atmarkit.co.jp/fwin2k/win2ktips/308strrpl/strrpl.html そこでreplace.wsfを作りましたが、正規表現がうまくいきません。 replace.wsfは正規表現を使う場合は "/ /g" で囲うらしいのですが urlのようなスラッシュ / が多いものを円記号 \ でエスケープしましたがうまくいきません。 さらに http://msdn.microsoft.com/ja-jp/library/aa293063(VS.71).aspx というサイトで任意の文字をドット . で置換したいんですができません。 以下書いたものを載せます 文字はアンダーバー _ で書いています strRepl="/http:[\/][\/]______.____.jp[\/]____/____[\/][0-9][0-9][0-9][0-9][\/][0-9][0-9][\/][0-9][0-9]/g"; /* 置換対象文字列 */ [\/]はかっこなしでも試しましたができませんでした [0-9]の部分は年月日が入ります。 replace.wsfで正規表現を実現させることができません。 正しい方法を教えてください!!

  • Wordのオートフォーマットについて

    Word2002で一括フォーマットを行うと、「書式変更:隠し文字」という吹き出しが変更履歴として現れます。 吹き出しから伸びた点線は、段落記号の直前を指しています。 しかしどうしてこんなところに隠し文字なのか、また、何がどう隠されたのかさっぱり分かりません。 元の文章は標準スタイルです。 一行だけ入力し、Enterキーで段落を変えました。 一行目の終わりと、まだ何も入力していない二行目の冒頭に段落記号がある状態です。 問題の箇所は二行目の冒頭です。 これは一体何なのでしょうか?

  • 条件に一致する行のみを選択し・・・

    全ての行のうち、C列にNote_on_cを含んでおり、かつI列が整数の行のみを選択し、それぞれの行のF列の数値を一括で加算/原産する方法はありますか? 例えば図の場合、15と20が整数かつNote_on_cという文字が入っているので、これらのF列の数値を一括で、+5したいのですが、どうすればよいのでしょうか。

  • エクセル 特定の文字列から範囲を指定

    エクセル 名前定義の範囲について質問です。 始まり・終わりの行・列を示す特定の文字列を設定し、 それを元に自動で範囲を変化させるようなことはできませんでしょうか。 例えば、 B1:列ここから D1:列ここまで A3:行ここから A6:行ここまで と書かれていた場合、 名前定義の範囲が自動で「B3:D6」となるような方法を探しています。 なお、 ・列を指定する文字列は必ず1行目に ・行を指定する文字列は必ずA列目に あるという想定です。 極力マクロを使用しない方法で、有効なものがございましたら ご指導のほどよろしくお願いします。

  • エクセル 名前定義の範囲について

    エクセル 名前定義の範囲について質問です。 始まり・終わりの行を示す特定の文字列を設定し、 それを元に自動で範囲の行数を変化させるようなことはできませんでしょうか。 例)A列に、行範囲を示す文字列を記述。  B列以降が実際の範囲となる。  A 1 この行から 2  3  4  5  6 この行まで 7 というように記述されていた場合、 「この行から」「この行まで」という文字列の位置を元に、 名前定義の範囲が自動で「B1:C6」となるような方法を探しています。 「この行から」の位置をA3に変更した場合、 名前定義された範囲も、自動で「B3:C6」に変化して欲しいのです。 ただし、文字列を元に変化するのは行だけで、列の範囲は固定で構いません。 極力マクロを使用しない方法で、有効なものがございましたら ご指導のほどよろしくお願いします。