2013-01-16 53 views
3

新手RegExp問題。我在一個文本文件中有JSON行,每個都帶有稍微不同的字段,但是如果它具有它,忽略其他所有內容,我想爲每行提取3個字段。我如何使用正則表達式(在編輯器或其他地方)來做到這一點?如何使用正則表達式來提取json字段?

例子:

"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,標題,標籤,

+5

我知道這可能不是你要找的東西,但你真的想要一個JSON解析器,不是這個正則表達式。 –

+5

不要試圖自己解析JSON。這是一個解決的問題。人們已經編寫,測試和調試過的代碼。無論何時您遇到其他人可能需要處理的編程問題,請查找現有的代碼,以便爲您解決問題。 –

回答

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

我覺得這是你問的。我會暫時提供解釋。這正則表達式(由/分隔 - 你可能不會有把那些的EditPad)匹配:

" 

一個文字"

(url|title|tags) 

任何的三個文字串「URL」,「標題」或「標籤」 - 在正則表達式,默認情況下圓括號用於創建組,並且管字符用於交替 - 就像一個邏輯'要麼'。要匹配這些文字字符,你必須逃避它們。

":" 

另一個文字字符串。

(

另一組的開始。 (第2組)

(

另一組(3)

 \\" 

文本字符串\" - 你必須轉義反斜線,因爲否則將被解釋爲轉義下一個字符,你永遠不知道那會做什麼。

 | 

或...

 [^"] 

除了雙引號的括號表示一個字符類/集,或一組字符匹配任何單個字符。任何給定的類只能匹配字符串中的一個字符。在課程開始處使用克拉(^)否定它,導致匹配器匹配課程中未包含的任何內容。

) 

結束組3的...

* 

星號使以前的正則表達式(在這種情況下,第3組),被重複零次或多次,在這種情況下使所述匹配器匹配任何可能在JSON字符串的雙引號內的東西。

)" 

組2的末尾和字面"

我已經在這裏做了一些非顯而易見的事情,這可能會派上用場:

  1. 集團2 - 將被分配到外地的實際字符串 - 在使用Backreferences取消引用。這在獲取實際值時非常有用。
  2. 表達式結尾處的i使得它不區分大小寫。
  3. 組1包含捕獲字段的名稱。

編輯:所以我看到標籤是一個數組。當我有機會思考它時,我會在一秒鐘內更新正則表達式。

你的新的正則表達式是:

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

所有我在這裏所做的是替換字符串的正則表達式我一直在使用("((\\"|[^"])*)"),以尋找陣列(\[("(\\"|[^"])*"(,"(\\"|[^"])*")*)?\])正則表達式。沒有那麼容易閱讀,是嗎?那麼,代我們的字符串正則表達式出去信S,我們可以把它改寫爲:

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

相匹配文字左括號(因此反斜槓),後面可以跟一個逗號分隔的字符串列表,並關閉托架。我在這裏介紹的唯一新概念是問號(?),它本身就是一種重複。通常被稱爲「使以前的表達式可選」,它也可以被認爲是恰好0或1匹配。

隨着我們同S符號,這裏是整個骯髒的正則表達式:

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

如果它有助於看到它在行動,這裏的a view of it in action.

+0

您好@FrankieTheKneeMan如果您想提取索引值,那麼這將如何更改,並且整個json以方括號和大括號開始,例如。 [{「index」:2931,「num_saves」:24 – Christa

1

爲什麼它必須是一個正則表達式對象?

在這裏,我們可以先使用一個哈希對象,然後去搜索它。

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} 

不,我要避免使用正則表達式,但你不覺得它會更容易把它一次一個步驟,直到你獲得的您想要進一步搜索的數據?只是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 

我們可以將其轉換爲一個JSON對象搜索MH哈希值。

/#{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中做這是不是你,但涉及我希望的標籤。

但是哎呀!看起來我們不能一下子用這種模式做所有的三件事,所以我會一次只做一件。

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 

對不起,最後一個。它將不得不以不同的方式處理。

0

我調整了正則表達式來在我自己的庫中使用JSON。下面詳細介紹了算法行爲。

首先,對JSON對象進行字符串化。然後,您需要存儲匹配的子字符串的開始和長度。例如:

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

對於一個JSON字符串,這個工程完全一樣的(除非您是逗號和花括號在這種情況下,我建議在執行正則表達式之前,你的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/

2

着這個問題是有點老,但我有我的瀏覽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" 
    } 
    } 
] 
+0

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [發表評論](/ review/low-quality-posts/11103218) – prasun

+0

你是對的,我改了它 – creep3007

+0

觀察:用上面的表達式,除非JSON格式不正確,當值長度爲0時,文本是對象或數組的一部分。最終它帶來了使用正則表達式和一點編程完全解析JSON的可能性! – Sancarn