14

初級正規表現の質問です。テキストファイルに JSON の行があり、それぞれフィールドがわずかに異なりますが、行ごとに抽出したいフィールドが 3 つあり、他のすべてを無視します。これを行うには、(編集パッドまたは他の場所で) 正規表現をどのように使用しますか?

例:

"url":"http://www.netcharles.com/orwell/essays.htm",
"domain":"netcharles.com",
"title":"Orwell Essays & Journalism Section - Charles' George Orwell Links",
"tags":["orwell","writing","literature","journalism","essays","politics","essay","reference","language","toread"],
"index":2931,
"time_created":1345419323,
"num_saves":24

URL、TITLE、TAGS、

4

5 に答える 5

27
/"(url|title|tags)":"((\\"|[^"])*)"/i

これがあなたが求めているものだと思います。ちょっと説明を加えます。この正規表現 ( / - で区切られる) は、次のように一致します。

"

リテラル".

(url|title|tags)

3 つのリテラル文字列 "url"、"title"、または "tags" のいずれか - 正規表現では、デフォルトで括弧を使用してグループを作成し、パイプ文字を使用して論理的な「or」のように交互に使用します。これらのリテラル文字に一致させるには、エスケープする必要があります。

":"

別のリテラル文字列。

(

別のグループの始まり。(グループ 2)

    (

別のグループ (3)

        \\"

リテラル文字列\"- バックスラッシュをエスケープする必要があります。そうしないと、次の文字をエスケープしていると解釈され、それが何をするかわからないからです。

        |

また...

        [^"]

二重引用符を除く任意の 1 文字 括弧は文字クラス/セット、または一致する文字のリストを示します。どのクラスも、文字列内の 1 文字に正確に一致します。クラスの先頭でカラット ( ^) を使用すると、それが無効になり、マッチャーはクラスに含まれていないものと一致します。

    )

グループ3終了…

    *

アスタリスクにより、前の正規表現 (この場合はグループ 3) が 0 回以上繰り返されます。この場合、Matcher は JSON 文字列の二重引用符内にある可能性のあるものと一致します。

)"

グループ 2 の終わり、およびリテラル".

私はここでいくつかの自明ではないことをしましたが、それは役に立つかもしれません:

  1. グループ 2 - 後方参照を使用して間接参照される場合- フィールドに割り当てられる実際の文字列になります。これは、実際の値を取得するときに役立ちます。
  2. 式の末尾の i は、大文字と小文字を区別しません。
  3. グループ 1 には、キャプチャされたフィールドの名前が含まれます。

編集:タグが配列であることがわかります。考える機会があれば、すぐに正規表現を更新します。

新しい正規表現は次のとおりです。

/"(url|title|tags)":("(\\"|[^"])*"|\[("(\\"|[^"])*"(,"(\\"|[^"])*")*)?\])/i

ここで行ったのは、これまで使用していた文字列の正規表現 ( "((\\"|[^"])*)") を、配列を検索するための正規表現 ( \[("(\\"|[^"])*"(,"(\\"|[^"])*")*)?\]) に置き換えただけです。読みやすいじゃないですか。文字列正規表現を文字に置き換えると、次のSように書き換えることができます。

\[(S(,S)*)?\]

これは、リテラルの左角かっこ (バックスラッシュ) と一致し、オプションで文字列のコンマ区切りリストと右角かっこが続きます。ここで紹介した唯一の新しい概念は、疑問符 ( ?) です。これは、それ自体が反復の一種です。一般に「前の式をオプションにする」と呼ばれますが、正確に 0 または 1 つの一致と見なすこともできます。

同じS表記法で、ダーティな正規表現全体を以下に示します。

/"(url|title|tags)":(S|\[(S(,S)*)?\])/i

実際の動作を確認するのに役立つ場合は、動作中のビューを次に示します。

于 2013-01-16T01:43:11.600 に答える
9

この質問は少し古いですが、PC で少しブラウジングしたところ、その表現が見つかりました。私は彼を GIST として渡しましたが、他の人に役立つ可能性があります。

編集:

# Expression was tested with PHP and Ruby
# This regular expression finds a key-value pair in JSON formatted strings
# Match 1: Key
# Match 2: Value
# https://regex101.com/r/zR2vU9/4
# http://rubular.com/r/KpF3suIL10

(?:\"|\')(?<key>[^"]*)(?:\"|\')(?=:)(?:\:\s*)(?:\"|\')?(?<value>true|false|[0-9a-zA-Z\+\-\,\.\$]*)

# test document
[
  {
    "_id": "56af331efbeca6240c61b2ca",
    "index": 120000,
    "guid": "bedb2018-c017-429E-b520-696ea3666692",
    "isActive": false,
    "balance": "$2,202,350",
    "object": {
        "name": "am",
        "lastname": "lang"
    }
  }
]
于 2016-02-01T11:50:20.557 に答える
0

私は自分のライブラリで JSON を扱うように正規表現を適応させました。以下にアルゴリズムの動作を詳しく説明しました。

まず、JSON オブジェクトを文字列化します。次に、一致した部分文字列の開始と長さを保存する必要があります。例えば:

"matched".search("ch") // yields 3

JSON 文字列の場合、これはまったく同じように機能します (コンマと中かっこを明示的に検索しない限り、正規表現を実行する前に JSON オブジェクトを事前に変換することをお勧めします (つまり、:、{、} と考えてください)。

次に、JSON オブジェクトを再構築する必要があります。私が作成したアルゴリズムは、一致インデックスから再帰的に遡って JSON 構文を検出することでこれを行います。たとえば、擬似コードは次のようになります。

find the next key preceding the match index, call this theKey
then find the number of all occurrences of this key preceding theKey, call this theNumber
using the number of occurrences of all keys with same name as theKey up to position of theKey, traverse the object until keys named theKey has been discovered theNumber times
return this object called parentChain

この情報を使用して、正規表現を使用して JSON オブジェクトをフィルタリングし、キー、値、および親オブジェクト チェーンを返すことができます。

私が作成したライブラリとコードは、http://json.spiritway.co/で確認できます。

于 2015-04-17T23:06:16.067 に答える
-1

なぜ正規表現オブジェクトでなければならないのですか?

ここでは、最初に Hash オブジェクトを使用してから検索することができます。

mh = {"url":"http://www.netcharles.com/orwell/essays.htm","domain":"netcharles.com","title":"Orwell Essays & Journalism Section - Charles' George Orwell Links","tags":["orwell","writing","literature","journalism","essays","politics","essay","reference","language","toread"],"index":2931,"time_created":1345419323,"num_saves":24}

その出力は次のようになります

=> {:url=>"http://www.netcharles.com/orwell/essays.htm", :domain=>"netcharles.com", :title=>"Orwell Essays & Journalism Section - Charles' George Orwell Links", :tags=>["orwell", "writing", "literature", "journalism", "essays", "politics", "essay", "reference", "language", "toread"], :index=>2931, :time_created=>1345419323, :num_saves=>24}

Regexp の使用を避けたいというわけではありませんが、さらに検索したいデータが得られるまで、一度に 1 つずつ実行する方が簡単だと思いませんか? ただのMHO。

mh.values_at(:url, :title, :tags)

出力:

["http://www.netcharles.com/orwell/essays.htm", "Orwell Essays & Journalism Section - Charles' George Orwell Links", ["orwell", "writing", "literature", "journalism", "essays", "politics", "essay", "reference", "language", "toread"]]

FrankieTheKneeman が提供したパターンを使用します。

pattern = /"(url|title|tags)":"((\\"|[^"])*)"/i

mh ハッシュを json オブジェクトに変換することで検索できます。

/#{pattern}/.match(mh.to_json)

出力:

=> #<MatchData "\"url\":\"http://www.netcharles.com/orwell/essays.htm\"" 1:"url" 2:"http://www.netcharles.com/orwell/essays.htm" 3:"m">

もちろん、これはすべてRubyで行われます。Rubyはあなたが持っているタグではありませんが、関連していることを願っています.

しかし、おっと!そのパターンだと3つ同時には無理みたいなので、念のため1つずつやっていきます。

pattern = /"(title)":"((\\"|[^"])*)"/i

/#{pattern}/.match(mh.to_json)

#<MatchData "\"title\":\"Orwell Essays & Journalism Section - Charles' George Orwell Links\"" 1:"title" 2:"Orwell Essays & Journalism Section - Charles' George Orwell Links" 3:"s">

pattern = /"(tags)":"((\\"|[^"])*)"/i

/#{pattern}/.match(mh.to_json)

=> nil

あのラストでごめんなさい。別の方法で処理する必要があります。

于 2014-12-30T17:17:50.007 に答える