web-dev-qa-db-ja.com

どのようにして正規表現を学びますか?

私はwhereに学ぶことを求めていません。私はオンラインでたくさんの優れたリソースや本などを見つけました。

しかし、一体どうやって私は彼らに取り組みますか。それの始まり、終わりはどこですか?正規表現プロセッサはいつテキストを進めますか?いつスタンドを保持して別の一致を試みますか?等.

エジプトのピラミッドの象形文字を理解しようとしているような気がします。

81
dumbBoy

オートマタ理論 の知識は理解のために重要だと思います。

オートマトンとは何か、そして 正規言語 がどのように定義されているかを理解すると、 正規表現 の理解がはるかに簡単になります。

特定の構文とさまざまな実装間の違いについて...まあ、覚えておかなければならないことがいくつかあります。 aids もあります。

編集

以下のコメントのいくつかは重要なポイントを提起しました:

  1. (ほとんどのプログラミング言語で実装されている)正規表現は、オートマトン理論における正規表現のスーパーセットであることを忘れないでください。良い理論的背景は開始するのに役立ちますが、すべてを説明するわけではありません。 (ありがとう、David Thornley)

  2. 複数のコメンターは、理論的基礎を学ばなくてもさまざまな正規表現構文を学ぶことが可能であると言います。構文がよくわからなくても習得できるのは本当ですが、OPが何を意味するのかを完全に理解することが私の印象でした。問題は、実際の根拠についてでした。プロセッサーはいつ進歩しますか?いつ止まるの?どのようにそれが一致すると判断しますか?それが基本であり、それが理論であり、それはオートマトン理論に基づいています。もちろん、エンジンの動作を知らなくても車を運転できます。しかし、「ガスは実際にどのようにしてそれを駆動させるのか」と尋ねられている場合-あなたはエンジンがどのように構築されるかについて話をする必要がありますしないでください君は?

68
littleadv

練習することによって。

ウェブスクレイピングを楽しんで学んだ。楽しみのためだけにやっているのではなかったと思います。

1つの例:お気に入りのスポーツWebサイトから最新のサッカー、テニス(実際に好きなスポーツ)のスコアを取得するコードを記述します。これを行うには、ページをロードするコードを記述し、正規表現でスコアを抽出して、コンソールまたはテキストファイルに出力します。選択する正規表現で、スコアのみを取得し、それ以外は取得しないようにしてください。時々、これは非常に難しい場合があります:-)

2番目の例:お気に入りのWebコミックの画像を取得するコードを記述し(たとえば Sinfest が好きです)、ハードドライブのどこかに保存します。正規表現のみを使用して「img」タグとそのコンテンツを取得します。どこかに保存されている場合は、オプションでそのタイトルも取得します。

36
Jalayn

あなたはリソースを求めているのではないことを知っていますが、 Mastering Regular Expressions by Jeffrey E.F. Friedlは、それらがどのように機能し、どのように使用するかを学びました。それらの多くを使用してさまざまなものを解析するようになった後でも、最初の章は私にとって新しいものでした。

あなたはそれらのいまいましい正規表現を理解したいですか?この本を読んでください。

23
Arkh

それの始まり、終わりはどこですか?正規表現プロセッサはいつテキストを進めますか?いつスタンドを保持して別の一致を試みますか?等.

あなたの目標を明確にすることから始めて、次にあなたの学習スタイルを構成する

あなたの質問について私を驚かせたのは、「どうすれば正規表現を学ぶのですか?」そしてすぐに「正規表現エンジンは内部でどのように機能するのですか?」あなたは、これら二つのことがお互いに何か関係があることを示唆しているように見えます。 たぶんあなたは何かを分解することによって、または自分で構築することによって何かがどのように機能するかを学ぶ人です。

初心者アプリケーションの場合、通常、ツールを効果的に使用するためにツールがどのように機能するかを理解する必要はありません。木材に穴を開けるために、ドリルモーターがどのように機能するかを知る必要はありません。ドリルを構築する方法ではなく、ドリルを使用する方法を理解する必要があります。

それであなたの目標は何ですか? 正規表現エンジンを構築する方法を学ぶつもりですか?またはビジネス問題を解決するために正規表現を効果的に使用する方法を学ぶつもりですか?これらの異なる目標を達成するには、おそらく異なる学習手法が必要です。

正規表現エンジンがどのように機能するかについてのあなたの特定の質問に取り組むために:それは依存します。正規表現への「古典的な」理論的アプローチは、非決定論的有限オートマトンの青写真として正規表現を使用し、次に同等の決定論的有限オートマトンを構築し、入力に対してそのオートマトンを実行することです。

いくつかの理由により、実際にこれを行う人はほとんどいない。まず、状態の数に可能な入力文字の数を掛けると、小さな正規表現でも非常に巨大な状態遷移テーブルが生成されます。もちろん、そのほとんどは圧縮できますが、それでも多くの移行ルールがあります。第二に、他のアプローチは通常より高速です。第三に、いわゆる「正規」式は、現代の正規表現ライブラリにあります。それらは通常の言語ではありません。有限オートマトン言語ではなく、プッシュダウンオートマトンによって認識されることがよくあります。

(私はこのすべてがどのように機能するかについての長いシリーズを書き始めましたが、 最初の12の記事 の後でSteamが不足しました。基本的な正規表現。)

実際の正規表現エンジンは、代わりに通常、バックトラッキング戦略を使用します。 10年以上前にJScriptエンジン用に構築した正規表現エンジンは、シーケンスを認識し、以前の状態に戻るためのプリミティブを含むバイトコード言語に正規表現をコンパイルします。次に、そのバイトコード言語用のインタープリターを作成しました。

正規表現を使用する方法をかなり確実に理解する前に、正規表現エンジンがどのように機能するかを理解しようとはしません。さまざまなエンジンの最適化戦略を掘り下げる前に、そのことに集中してください。

19
Eric Lippert

どのようにそれらに取り組むのですか?

新しいもののように:

10 Study
20 Practice
30 goto 10

調査

私は、成功している教師のほとんどが、最初に対象に少し背景を提供することから、あらゆる対象を教え始めていることがわかります。何を学んでいるか、そして最も重要なのはwhy何を学んでいるかというコンテキストを持つことが重要です。

それはすべて文字列マッチングです

正規表現は、テキスト内のパターンを照合する手段です。それ自体が宣言型言語であり、他の多くのプログラミング言語に組み込まれています。

宣言型の言語であることを強調したいのですが、正規表現はwhatと一致する文字列を表現するのに役立ちますが、は表現しませんhowプログラムはマッチングを実行します。このため、別のRegExパーサーを使用するだけで、同じプログラミング言語で非常に速く、非常にゆっくりと正規表現を使用できます。

正規表現を作成する理由は、ほとんどのプログラミング言語の作成で同じです。プログラマーは何度も何度も同じ複雑なタスクを実行していることに気づき、コードをより簡単に記述する方法が必要だと判断しました。

一部の人は、私の前の文について次のように言って文句を言うでしょう(そしてすべきです)。

RegExはプログラムを単純化しません。

それは本当です

RegExはプログラムを単純化しません、RegExはwriteを作成しますより簡単なプログラム。すべての正しいケースが正しく一致し、すべての正しくないケースが一致していないことを確認するには、テストを徹底する必要があります。 「すべて」をテストするのは本当に難しく、複雑なパターンでは「ほとんど」をテストするのが本当に難しいです。最悪の場合でも、「一部の」ケースをテストする必要があります。

ブラウザのライブで簡単にテストできるため、またRegExリテラルを使用しているときに文字列のエスケープを行う必要がないため、JavaScriptのRegExエンジンを義務的に選択したいくつかの例を組み込むことができます。

通常の文字列照合を行う場合、ある文字列値を別の文字列値に対してテストします。それらはどこから来てもかまいませんが、最終的には2つの文字列を互いに比較する必要があります。

if ( 'foo' == 'bar' ) doSomething();

それは決して何もしないので、その例は吸います

if ( foo == 'bar' ) doSomething();

ずっといい;現在、実際に何かが行われるかどうかは事前にわかりません。これで、ユーザー入力の受け入れを開始できます。

if ( Prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();

すばらしい。ユーザーがbarを入力できるようになり、"bar"が機能していない、または「BAR」が機能していない、またはユーザーが機能しているというバグレポートをユーザーが受け取るまで、何かが起こります。 veはBRAを100回入力しても何も起こりません。

スペルミスと余分な文字'bar' != 'BAR'を無視して、プログラマは、文字の大文字と小文字の違いをテストする方法を考える必要があります。

簡単な解決策は、toLowerCaseを使用することです。それは素晴らしい働きをしますが、something == 'color'を照合するときにアメリカ英語よりもイギリス英語を使用しているユーザーはどうですか?次に、something == 'color' || somthing == 'colour'と一致させる必要があります。

一言で言えば、単純で単純なパターンは、多くの反復的なコードにすぐに変わります。

色の例は、次のものと単純に一致させることができます。

/colou?r/.test( something )

正規表現の基本をしっかりと理解することで、ホイールの再発明に費やす時間を大幅に削減できます。

どこで勉強するか

正規表現を実装するほとんどの言語には、その言語で正規表現を使用する特定の構文に使用できるリソースが少なくとも1つあります。 1つ JavaScriptはMDNにあります

読んでください。
それのすべて。
その後、もう一度お読みください。

学ぶには時間がかかり、投資だと考えてください。RegExを学ぶのに1時間かかるので、次に文字列パターンマッチングを行う必要があるときは1時間節約でき、その後はさらに1時間節約できます。

練習

RegExのすべてを読んだ後、おそらくそのほとんどを理解できないでしょう。これは、実際には何もしていないためです。

この例でJSを選択した理由を述べましたが、ブラウザーでJSをいじってください。すばやく、URLバーから直接実行できます。

JSには、RegExを使用するいくつかの異なる簡単な方法があります。

string.match( regex )
regex.exec( string )
regex.test( string )

次のような単純なものから始めます:

javascript:'color'.match(/colou?r/);

ドアに足を入れる簡単な方法です。それを試してみて、一致するものと一致しないものを確認してください。

練習に行き詰まったら、30に進んでください。あなたはもっと学ぶために読む必要がありますが、あなたが学んだことを本当に理解するために練習する必要があります。

6
zzzzBov

Brian Kernighanが本 Beautiful Code に簡単な正規表現プロセッサを書いています。リソースを探しているのではないことは承知していますが、基本的な実装を内部で確認すると役立つ場合があります。

5
Michael Easter

通常の開発では、デバッグコードは非常に有用な洞察を提供します。正規表現に違いはありません。したがって、広告のように聞こえるリスクがある場合は、 RegexBuddy を取得します。これは、式と入力文字列を処理するときにエンジンが実行していることを視覚的に表示するための優れたツールを備えています。

4
John Fisher

優れたリファレンスに加えて、実際にlearnする方法は、優れた学習ツールを使用することです。 1つはオープンソースの Vim エディターを使用し、2つのオプションを設定します。

  1. :set incsearch ...コマンドラインで検索パターンを入力すると、エディターはオンザフライで最初に一致するテキストにジャンプし、一致するものを正確に強調表示します。一致しないものを入力すると、Vimはカーソルをジャンプして、開始時の位置に戻ります。
  2. :set hlsearch ...これにより、現在のRE検索に一致するすべてのテキストの背景が強調表示されます。

もう1つは、無料のツールコール RegExCoach を使用することです。検索するテキストを貼り付けてから、別のウィンドウで正規表現を作成します。 Vimと同様に、成功した試合をその場で強調します。

3
Firstrock

簡単な質問に簡単な答えをあげましょう。まず、正規表現(RegEx)とは何か、つまり何をするか、何に使用されるかを理解する必要があります。次に、始めるのに最適なツールです。

  1. それは何ですか? RegExは、パターンマッチングを表現するための言語です。つまり、それを使用して、テキスト内のパターンを認識または検出する文字の組み合わせを作成できます。これはどのように役立ちますか?プログラミングでは、特定のソース(ユーザー入力、Webページなど)からのテキストを照合し、特定のパターンのテキストが含まれているかどうかを検出するようにコンピューターに指示できます。たとえば、ピリオド(。)は任意の文字(文字または数字)を表します。中かっこ内の数値は反復回数を表すため、 "。{1,30}"は1〜30回繰り返される任意の文字を示します。つまり、空の文字列は使用できず、30を超えることはできません。文字。そして、それはそこから続きます。

  2. 学習を始めるには?私が見た絶対的に最高のツールは Expresso ですが、それはWindows専用です。非常に広範なGUIがあり、式に追加する要素をクリックすると、テスターがさまざまな入力と照合して結果を確認します。 Macで良いものを見たことはありません(ただし、VMWareでWindowsを実行しているため、Macバージョンは必要ありません)。Linuxを探すのに多くの時間を費やしていません。

3
Jay Imerman

正規表現はすぐに非常に複雑になる可能性があるため、チュートリアルを使用して学習を開始することをお勧めします。正規表現の最も単純な形式は、検索対象を表す文字列であることを理解してください。残念ながら、特別な検索ルールを定義できるようにするには、特定の文字が必要であり、これらの文字をエスケープする必要があります。そうしないと、無効または不正な正規表現が作成されます。

私のアドバイスは、あなたが探しているものの例から始めて、それをエスケープすることです。つまり、かっこで何かを探していた場合は、検索しているテキストでそのような文字列を例に取ってください:_(this is an example of something you'd want to find)_

最初に文字をエスケープして、リテラル文字を検索します:\(this is an example of something you'd want to find\)

テストして、サンプルが正しく検出されることを確認してください。次に、式を一般化して、見つけた例だけでなく、そのようなテキストを見つけます。したがって、次のようになります:\([^)]*\)(0を含む、任意の数の出現に対して「)」ではない任意の文字を意味します)。

もう一度テストして、例だけでなく他の例も見つかることを確認してください。より複雑で頻度の高い正規表現をインターネットで検索し、既存の正規表現でパッチを適用して、すべての可能性を心配する必要がないようにします。

それだけです。そして、ああ、\ Q ...\Eを学び、愛する。ほとんどの正規表現言語では、\ Qはリテラルパターンの始まりを示し、\ Eは終わりを示します。これは、特に高度なパターンの検索に対処する必要があり、それらをエスケープする方法がわからない場合に備えています。これにより、私の人生は2度以上救われました。

3
Neil

他の2つの良い答えは、正規表現の背後にある理論を学び、実践することです。これらはどちらも素晴らしいアドバイスです。また、深刻な問題を解決するための優れた視覚的正規表現ツールを入手することをお勧めします。

たとえば、RegexBuddyには、正規表現の実行をステップ実行できるビジュアルデバッグモードがあり、ハイライトと説明テキストを介して正規表現エンジンが何であるかを示します各ステップで行います。サイトには このデバッグを示すビデオ があります。

2
Steven

私たちがあなたに与えることができるすべては、学ぶためのより多くのリソースです。この質問自体がリソースです。

ちなみに、このサイトから正規表現を簡単に学べました。 http://www.regular-expressions.info/

2
Thiago Negri

まず、基本的な文字列比較から始めます。とても簡単ですが、それほど強力でもありません。

次に、「ギリシャ語」と「ギリシャ語」を同等に比較できるように、大文字と小文字を区別しない比較が必要になる場合があります。これはもう少し強力です。

ある日、スペルのわずかな違いに気づいても、2つの単語が同等に比較されるのを妨げるべきではありません。あなたは座って、これを行うコードを書いて、満足しています。

もう少し抽象化して、「ize」で終わるすべての単語を、英国のスペルの兄弟と同等に比較したい場合があることに気づくまでは。または、いくつかの文字列を特定の回数繰り返します。そしてもちろん、これらすべてを組み合わせる必要があります。

等々。最後に、ほとんどの場合、すべてのキャラクターが自分自身を表すわけではないという表記法で終わります。他に正規表現はありません。文字列のセットの説明として見ることができます。

そして、それはかなり簡単で、次の3つの基本原則に帰着します。

基本的な正規表現があります。それ自体を表す文字、文字クラス、大文字の\ dや\ p {Lu}のような文字クラスの便利な省略形ではありません。

そして、それらを組み合わせるいくつかの可能性があります:r1とr2が正規表現である場合、r1r2 r1 | r2(r1)もそうです。

最後に、繰り返しの修飾子:r? r * r + r {n、m}

これはあなたが知る必要があるほとんどのものです。それが必要なときにルックアップできる他の何か。

2
Ingo

私にとって、構築中に正規表現が何に一致するかを確認することは、私の人生を本当に助け、それらをよりよく理解するのに役立ちました。

これを行うには、ターゲットテキストを含むファイルをEmacsで開き、isearch-forward-regexpコマンドを使用します。正規表現を入力すると、Emacsは何が一致しているかを示します(これが「isearch」の部分です)。

Emacsでコマンドを実行するには、<ESC>xisearch-forward-regexpを使用できます。

1
jwernerny

字句アナライザーとパーサーを構築するために使用されるflexとbisonを学ぶことで、正規表現を学びました。正規表現なしでパーサーを作成することはできません。本 lexx and yacc は、あまり速く動かずに理論をウォークスルーするのに非常に優れています。

基本的に、最近のほとんどすべての正規表現エンジンは同じ原則に従っています。それらはすべて 有限状態マシン であり、本当にそれを理解すれば、ほとんどすべてのコードを書くことができます。これは、再帰を学習するのと似ており、一度取得すると、それを本能的に問題に適用します。それらは適切なツールで簡単に解決できますが、それがなければ非常に困難です。

正規表現と比較したときのlexxとyaccの学習に関するもう1つのことは、内部でそれらがどのように機能するかを学習することです。プログラムがどのように先を見越しているか、なぜそれが一致を終了するのか、どのようにデータを保持するか、などなど。ポインターを理解することは絶対に必要ですが、lexxとyaccを入手して最初からやり直すと、質問したすべてのことを学ぶことができ、残りのキャリアのための非常に強力なツールを利用できます。

この question には、学習用のリソースと、一緒に投げたフレックススケルトンが含まれています。

1
Spencer Rathbun

もう、私はまず問題を解決する簡単な方法がないことを確認しようとします/文字列を「トークン化」します。

見つからない場合は、文字列から必要なものと一致させようとするのではなく、不要なものと一致しないことが問題であると考えています。これは主に正規表現が貪欲だからです。しかし、それは私が欲しいものを得るためのアプローチとして私によく役立ちました。

次に例を示します。

string = "Sep 22 19:57:38 Host fcron[9137]: \
          Job fbsetbg -r $HOME/backgrounds/ \
          started for user user (pid 9138)"

分に合わせるには:

string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/                 # correct and good

時間とともに他のすべてのものを見つけるのではなく、明確な境界を見つけるようにしてください。

例は少し工夫されていますが、思いつくことができるすべてです。

1
frogstarr78

私が使用したアプローチの1つは、構文の更新が必要な一連のオープンソースプロジェクトを見つけて、多くの正規表現で構成される、ますます複雑になるsedスクリプトを作成することでした。

このスクリプトは、各オープンソースプロジェクトのさまざまなファイルに対して実行する必要がありました。次に、さまざまなスタイルのさまざまなプロジェクトに対して実行します。 %s/before/afterのような非常に単純なものから始めたところ、あまりにも多くのケースに一致することがわかりました。それを防ぐために私はより多くのものを追加しました。次に、さまざまな変更が必要なさまざまな構文スタイルを使用するさまざまなプロジェクトを見つけました。

最後に私はで終わった

  • 正規表現に関する優れたスキルと知識
  • セッドとの良いスキル
  • 多くのオープンソースプロジェクトを支援
  • 私のgithubプロファイルに表示される多くの貢献活動を取得する
  • 仮想ツールベルト用のもう1つの優れた「スイスアーミーナイフ」ツール

そして、このアプローチで助けられたのは

  • 浮気せずに実際の目標を達成する
  • (正規表現)スキルを、より大きなモチベーションを持つより大きな目標の一部として使用します。
  • 他のコードを変更して変更をレビューすることにより、私が学んだスキルの証明を示すことができます。

Rubyやjavascriptなど、さまざまな言語のサイトがたくさんあり、すぐに満足できる表現やサンプルテキストをいじってみることも伝えます。これらは:

1つのサイトで複数の言語の正規表現

マッチグループに焦点を当てる:

1
Michael Durrant

正規表現を学ぶことは、九九を学ぶことに似ています-はい、その背後にある考えを理解する必要がありますが、結局は、それを頻繁に繰り返し行う必要があります。

私が学んでいたとき、私は自分で1日に2、3の正規表現演習を行うことを目標に設定しました。実際には、これは少なくとも1日に1回は、画面の文字列またはテキストを見て、「ここからすべてのメールアドレスを取得できるか」または「名詞ではなく動詞として使用される単語「コード」の出現」など.

それを数週間行うことは本当に報われました-そしてもちろん、定期的なレビューと復習が必要です。私は1の期限が近づいています。

リアルタイムで正規表現をテストできるので、このオンラインツールも役に立ちました。 http://www.gethifi.com/tools/regex

0