-
1 # 莫談世事短
-
2 # 52sissi
全力以赴地進入資料集是從事資料科學工作的任何人的使命之一。通常,這意味著要進行數字運算,但是當我們的資料集主要基於文字時,我們該怎麼辦?我們可以使用正則表示式。在本教程中,我們將仔細研究如何在Python中使用正則表示式(regex)。
正則表示式(regex)本質上是文字模式,可用於自動搜尋和替換文字字串中的元素。這可以使清理和使用基於文字的資料集變得更加容易,從而省去了手動搜尋大量文字的麻煩。
正則表示式可以在多種程式語言中使用,並且已經存在很長時間了!
不過,在本教程中,我們將學習Python中的正則表示式,因此需要基本熟悉關鍵的Python概念,例如if-else語句,while和for迴圈等。在本教程結束時,您將熟悉Python regex的工作原理,並能夠使用Python regex模組中的基本模式和功能re來分析文字字串。您還將獲得有關正則表示式如何與熊貓配合使用以處理大型文字語料庫的介紹。
讓我們深入研究有關每個人最不喜歡的電子郵件型別的一些資料:垃圾郵件和欺詐。
我們的任務:分析垃圾郵件
在本教程中,我們將使用Kaggle的欺詐電子郵件語料庫。它包含1998年至2007年之間傳送的數千種網路釣魚電子郵件。它們非常有趣,易於閱讀。
您可以在這裡找到完整的語料庫。但是,我們將從使用一些電子郵件學習基本的正則表示式命令開始。如果需要,您也可以使用我們的測試檔案,也可以在完整的語料庫中嘗試使用。
介紹Python的Regex模組
首先,我們將透過開啟測試檔案,將其設定為只讀並讀取來準備資料集。我們還將其分配給變數fh(用於“檔案控制代碼”)。
請注意,我們在目錄路徑之前加r。此技術將字串轉換為原始字串,這有助於避免某些機器讀取字元的方式引起的衝突,例如Windows上目錄路徑中的反斜槓。
但這並沒有給我們確切的需求。如果您看一下我們的測試檔案,我們可以找出原因並修復它,但是,讓我們使用Python的re模組並使用正則表示式來做吧!
我們將從匯入Python的re模組開始。然後,我們將使用一個名為的函式re.findall(),該函式返回在正在檢視的字串中定義的模式的所有例項的列表。
外觀如下:
這與原始Python的長度基本相同,但這是因為這是一個非常簡單的示例。您嘗試做的越多,Python正則表示式就可以為您節省更多的精力。
在繼續之前,讓我們仔細看看re.findall()。此函式採用形式為的兩個引數re.findall(pattern, string)。在這裡,pattern代表我們要查詢的子字串,並string代表我們要在其中查詢的主字串。主字串可以包含多行。在這種情況下,我們讓它fh使用選定的電子郵件來搜尋所有檔案。
該.*是一個字串模式的簡寫。正則表示式透過使用這些速記模式來查詢文字中的特定模式而起作用,因此讓我們看一下其他一些常見示例:
常見的Python正則表示式模式
我們re.findall()上面使用的模式包含一個完整拼寫的字串"From:"。當我們確切地知道我們要查詢的內容(精確到實際字母以及它們是否為大寫或小寫)時,這很有用。如果我們不知道我們想要的字串的確切格式,我們將會迷路。幸運的是,正則表示式具有解決此情況的基本模式。讓我們看看在本教程中使用的那些:
1)w匹配字母數字字元,表示az,AZ和0-9。它還與下劃線_和破折號-相匹配。
2)d 匹配數字,表示0-9。
3)s 匹配空白字元,包括製表符,換行符,回車符和空格字元。
4)S 匹配非空格字元。
5).匹配除換行符外的任何字元n。
掌握了這些正則表示式模式後,您將在繼續進行解釋的同時快速理解上面的程式碼。
使用正則表示式模式
現在,我們可以.*在re.findall("From:.*", text)上面的行中解釋的用法。讓我們.先來看:
透過在.旁邊新增一個From:,我們可以在其旁邊查詢另一個字元。因為.查詢除以外的任何字元n,所以它捕獲了我們看不到的空格字元。我們可以嘗試更多的點來驗證這一點。
看起來加點確實為我們獲得了線的其餘部分。但是,這很繁瑣,而且我們不知道要新增多少點。這是星號符號*出現的位置。
*匹配模式左側的零個或多個例項。這意味著它將尋找重複模式。當我們尋找重複的模式時,我們說搜尋是“貪婪的”。如果我們不尋找重複的模式,則可以將搜尋稱為“非貪婪”或“懶惰”。
讓我們構建一個貪婪的搜尋.用*。
因為*匹配在其左側指示的模式的零個或多個例項,並且.位於此處的左側,所以我們能夠獲取From:欄位中的所有字元,直到行尾。這將用精美簡潔的程式碼打印出整行。
我們甚至可以更進一步,僅隔離名稱。讓我們使用它re.findall()來返回包含模式的行列表,"From:.*"就像之前一樣。match為了整潔,我們將其分配給變數。接下來,我們將遍歷列表。在每個迴圈中,我們將re.findall再次執行,匹配第一個引號以僅選擇名稱:
注意,我們在第一個引號旁邊使用了反斜槓。反斜槓是一個特殊字元,用於轉義其他特殊字元。例如,當我們想將引號用作字串文字而不是特殊字元時,可以使用反斜槓將其轉義,例如:\"。如果我們不使用反斜槓轉義上面的模式,它將變為"".*"",Python直譯器將其讀取為兩個空字串之間的句點和星號。它將產生錯誤並破壞指令碼。因此,至關重要的是我們在這裡用反斜槓將引號引起來。
匹配第一個引號後,.*獲取行中的所有字元,直到下一個引號也被轉義為模式。這使我們得到的名稱只是帶引號的名稱。該名稱也列印在方括號中,因為re.findall返回的匹配項在列表中。
如果我們想要電子郵件地址怎麼辦?
看起來很簡單,不是嗎?僅模式不同。讓我們來看一看。
這是我們僅匹配電子郵件地址的前部分的方式:
電子郵件總是包含一個@符號,因此我們從它開始。電子郵件中@符號前的部分可能包含字母數字字元,這w是必需的。但是,由於某些電子郵件包含句點或破折號,所以這還不夠。我們新增S以查詢非空白字元。但是,w\S只會得到兩個字元。新增*以查詢重複。因此,模式的前部如下所示:\w\S*@。
現在檢視@符號後面的模式:
域名通常包含字母數字字元,句點和短劃線,因此a .可以。為了使它更貪婪,我們使用擴充套件了搜尋範圍*。這使我們可以匹配任何字元,直到行尾。
如果我們仔細觀察這條線,會發現每封電子郵件都封裝在尖括號<和>中。我們的模式.*包括右括號>。讓我們對其進行補救:
電子郵件地址以字母數字字元結尾,因此我們將模式設定為w。因此,在@符號後面有.*\w,這表示我們想要的模式是一組以字母數字字元結尾的任何型別的字元。不包括>。
因此,我們的完整電子郵件地址格式如下所示:\w\S*@.*\w。
!這需要花費很多時間。接下來,我們將介紹一些通用re功能,這些功能在開始重新組織語料庫時將非常有用。
常用的Python正則表示式函式
re.findall()無疑是有用的,但它不是我們可以使用的唯一內建函式re:
1)re.search()
2)re.split()
3)re.sub()
在使用它們為我們的資料集新增一些順序之前,讓我們一一看一下。
研究()
While re.findall()匹配字串中某個模式的所有例項並在列表中返回它們,re.search()匹配字串中一個模式的第一個例項,並將其作為re匹配物件返回。
像一樣re.findall(),re.search()也有兩個引數。第一個是要匹配的模式,第二個是要在其中找到模式的字串。在這裡,我們將結果分配給match變數以保持整潔。
由於re.search()返回re匹配物件,因此無法透過直接列印來顯示名稱和電子郵件地址。相反,我們必須首先對該group()函式應用該函式。我們已經在上面的程式碼中列印了這兩種型別。如我們所見,group()將match物件轉換為字串。
我們還可以看到,列印match顯示的屬性超出字串本身,而列印match.group()僅顯示字串。
re.split()
假設我們需要一種快速的方法來獲取電子郵件地址的域名。我們可以透過三個正則表示式操作來做到這一點,如下所示:
第一行很熟悉。我們返回一個字串列表,每個字串包含From:欄位的內容,並將其分配給變數。接下來,我們遍歷列表以查詢電子郵件地址。同時,我們迴圈訪問電子郵件地址,並使用該re模組的split()功能將每個地址切成兩半,用@符號作為分隔符。最後,我們列印它。
re.sub()
另一個方便的re功能是re.sub()。就像函式名稱所暗示的那樣,它替換字串的一部分。一個例子:
我們之前已經在第一行和第二行看到了任務。在第三行,我們re.sub()在上應用address,這是From:電子郵件標題中的完整欄位。
re.sub()需要三個引數。第一個是要替換的子字串,第二個是我們要替換的字串,第三個是主字串本身。
正則表示式與pandas
現在,我們掌握了Python正則表示式的基礎知識。但是通常對於資料任務,我們實際上並沒有使用原始的Python,而是使用了pandas庫。現在,將我們的正則表示式技能帶入熊貓工作流程,將其提升到一個新的水平。
如果您以前從未使用過熊貓,請不要擔心。我們將逐步遍歷程式碼,以免您迷路。但是,如果您想更詳細地瞭解熊貓,請檢視我們的熊貓教程或我們提供的有關numpy和熊貓的完全互動式課程。
使用Python Regex和Pandas對電子郵件進行排序
我們的語料庫是一個包含數千封電子郵件的單個文字檔案(不過,同樣,在本教程中,我們使用的是一個只有兩個電子郵件的較小檔案,因為在整個語料庫上列印正則表示式工作的結果會使這篇文章過長)。
我們將使用正則表示式和熊貓將每封電子郵件的各個部分分類為適當的類別,以便可以更輕鬆地閱讀或分析語料庫。
我們將每封電子郵件分為以下類別:
1)sender_name
2)sender_address
3)recipient_address
4)recipient_name
5)date_sent
6)subject
7)email_body
這些類別中的每一個都將成為我們的熊貓資料框(即我們的表格)中的一列。這將使我們更輕鬆地分別處理和分析每個列。
我們將繼續處理我們的小樣本,但是值得重申的是,正則表示式使我們可以編寫更簡潔的程式碼。簡潔的程式碼減少了我們的機器必須執行的運算元量,從而加快了我們的分析過程。使用我們的兩封電子郵件的小檔案,並沒有太大的區別,但是,如果您嘗試使用和不使用正則表示式來處理整個語料庫,您將開始看到其優勢!
準備指令碼
首先,讓我們匯入所需的庫,然後再次開啟檔案。
除了re和之外pandas,我們email還將匯入Python的軟體包,這將有助於電子郵件的正文。僅使用正則表示式時,電子郵件的主體相當複雜。它甚至可能需要足夠的清理才能保證有自己的教程。因此,我們將使用完善的email軟體包來節省一些時間,讓我們專注於學習正則表示式。
我們還建立了一個空列表emails,用於儲存字典。每本詞典將包含每封電子郵件的詳細資訊。
現在,讓我們開始應用正則表示式!
注意:為簡潔起見,我們剪裁了上面的列印輸出。如果您在自己的機器上列印此檔案,它將顯示其中包含的所有內容,contents而不是...像上面那樣結束。
我們使用re模組的split函式將整個文字塊分割fh為單獨的電子郵件列表,然後將其分配給變數contents。這很重要,因為我們希望透過使用for迴圈遍歷列表來逐一處理電子郵件。但是,我們如何知道按字串分割"From r"?
我們之所以知道這一點,是因為在編寫指令碼之前我們已經查看了檔案。我們不必細讀其中的數千封電子郵件。只是前幾個,看看資料的結構是什麼樣子。只要有可能,最好在開始使用程式碼之前先關注實際資料,因為您經常會發現諸如此類的有用功能。
我們已經截取了原始文字檔案的螢幕截圖:
電子郵件以“ From r”開頭
綠色方框是第一封電子郵件。藍色方框是第二封電子郵件。如我們所見,這兩封電子郵件均以開頭"From r",並以紅色框突出顯示。
我們在本教程中使用欺詐電子郵件語料庫的原因之一是,當資料雜亂無章,不熟悉且沒有文件時,我們不能僅僅依靠程式碼來整理資料。這將需要一雙人眼。正如我們剛剛顯示的,我們必須研究語料庫本身以研究其結構。
像這樣雜亂無章的資料可能需要大量清理。例如,即使我們使用本教程將要構建的完整指令碼來計算此集合中的3977封電子郵件,但實際上還有更多。某些電子郵件實際上並不以開頭"From r",因此不會單獨計算。(不過,為了簡潔起見,我們將繼續處理該問題,並用分隔所有電子郵件"From r"。)
還要注意,我們contents.pop(0)用來擺脫列表中的第一個元素。這是因為"From r"字串在第一封電子郵件之前。拆分該字串後,它將在索引0處生成一個空字串。我們將要編寫的指令碼是為電子郵件設計的。如果我們嘗試在空字串上使用它,則可能會引發錯誤。擺脫空字串可以使我們避免破壞指令碼。
使用For迴圈獲取每個名稱和地址
接下來,我們將使用contents列表中的電子郵件。
在上面的程式碼中,我們使用for迴圈來遍歷,contents因此我們可以依次處理每封電子郵件。我們建立了一個詞典,emails_dict其中包含每封電子郵件的所有詳細資訊,例如發件人的地址和姓名。實際上,這些是我們發現的第一批物品。
這是一個三步過程。首先從尋找From:領域開始。
在第1步中,我們From:使用re.search()函式查詢整個欄位。該.裝置除了任何字元n,並且*其延伸到行的結尾。然後,我們將其分配給變數sender。
但是,資料並不總是那麼簡單。它可能包含驚喜。例如,如果沒有From:欄位怎麼辦?該指令碼將引發錯誤並中斷。我們在步驟2中避免了這種情況下的錯誤。
為了避免由於缺少From:欄位而導致的錯誤,我們使用一條if語句來檢查sendernot None。如果是,我們分配s_email和s_name的值,None以便指令碼可以繼續執行而不是意外中斷。
如果您在自己的檔案中使用本教程,則可能已經意識到使用正則表示式會變得混亂。例如,這些if-else語句是在編寫主體時對主體使用反覆試驗的結果。編寫程式碼是一個反覆的過程。值得注意的是,即使本教程看起來很簡單,實際實踐也需要進行更多的實驗。
在第2步中,我們使用之前的regex模式\w\S*@.*\w,該模式與電子郵件地址匹配。
我們將對名稱使用其他策略。每個名稱都由左側:子字串的冒號()"From:"和<右側電子郵件地址的左尖括號()界定。因此,我們使用它:.*<來查詢名稱。我們擺脫:並<從每個結果的時刻。
現在,讓我們打印出程式碼的結果以檢視它們的外觀。
同樣,我們有匹配物件。每次我們將re.search()字串應用於字串時,都會生成匹配物件。我們必須將它們變成字串物件。
我們這樣做之前,記得,如果沒有From:現場,sender將具有的價值None,因此也將s_email和s_name。因此,我們必須再次檢查這種情況,以便指令碼不會意外中斷。讓我們看看如何首先構建程式碼s_email。
在步驟3A中,我們使用一條if語句檢查s_emailnot None,否則它將引發錯誤並破壞指令碼。
然後,我們只需將s_emailmatch物件轉換為字串並將其分配給sender_email變數。我們將其新增到emails_dict字典中,這將使我們日後將細節轉換為pandas資料框變得異常容易。
我們s_name在步驟3B中所做的幾乎完全相同。
正如我們以前那樣,我們首先檢查s_name是不是None在步驟3B。
然後,在將字串分配給變數之前,我們兩次使用re模組的re.sub()函式。首先,我們刪除冒號和它與名稱之間的所有空白字元。我們:s*用一個空字串代替""。然後,我們刪除空格字元和名稱另一邊的尖括號,再次用空字串替換它。最後,在將字串分配給之後sender_name,我們將其新增到字典中。
讓我們檢查一下結果。
完善。我們已經隔離了電子郵件地址和發件人的姓名。我們還將它們新增到字典中,該字典將很快投入使用。
現在我們已經找到了發件人的電子郵件地址和名稱,我們將執行完全相同的步驟來獲取字典的收件人的電子郵件地址和名稱。
首先,我們找到To:領域。
接下來,我們搶先在場景recipient是None。
如果recipient不是None,則用於re.search()查詢包含電子郵件地址和收件人姓名的匹配物件。否則,我們傳遞r_email和r_name的值None。
然後,將匹配物件轉換為字串並將其新增到字典中。
由於From:和To:欄位的結構相同,因此我們可以對兩者使用相同的程式碼。我們需要為其他欄位定製略有不同的程式碼。
獲取電子郵件的日期
現在確定傳送電子郵件的日期。
我們Date:為From:和To:欄位獲取具有相同程式碼的欄位。
並且,就像我們對這兩個欄位所做的一樣,我們檢查Date:分配給date_field變數的欄位是否不是None。
我們已經列印了出來,date_field.group()以便我們可以更清楚地看到字串的結構。它包括日期,DD MMM YYYY格式的日期和時間。我們只想要日期。日期的程式碼與姓名和電子郵件地址基本相同,但更為簡單。也許唯一令人困惑的是正則表示式模式\d+\s\w+\s\d+。
日期以數字開頭。因此,我們用d它來解釋它。但是,作為日期的DD部分,它可以是一位或兩位數字。在這裡+變得重要。在Python正則表示式中,+匹配其左側1個或多個模式例項。d+因此,無論日期是DD還是一兩位數字,它都將與日期的DD部分匹配。
在那之後,有一個空間。這是由佔的s,它查詢空白字元。因此,該月由三個字母組成w+。然後它撞到另一個空間s。年份由數字組成,因此我們d+再次使用。
完整模式\d+\s\w+\s\d+起作用的原因是它是一個精確的模式,在兩側均以空格字元為界。
接下來,我們None像以前一樣檢查值。
如果date不是None,則將其從匹配物件轉換為字串,並將其分配給變數date_sent。然後,將其插入字典中。
在繼續之前,我們應該注意一個關鍵點。+並且*看起來相似,但它們可以產生非常不同的結果。讓我們以日期字串為例。
如果使用*,則將匹配零個或多個匹配項。+匹配一個或多個事件。我們已經列印了兩種情況的結果。有很大的不同。如您所見,+獲取完整日期,而*獲取空格和數字31。
接下來,是電子郵件的主題行。
獲取電子郵件主題
和以前一樣,我們使用相同的程式碼和程式碼結構來獲取所需的資訊。
現在我們對Python正則表示式的使用越來越熟悉了,不是嗎?它與以前的程式碼大致相同,不同之處在於,我們"Subject: "用空字串代替僅獲取主題本身。
獲取電子郵件的正文
要插入字典的最後一項是電子郵件的正文。
將標頭與電子郵件正文分開是一項非常複雜的任務,尤其是當許多標頭以一種或另一種方式不同時。在原始的無組織資料中很少發現一致性。對我們來說幸運的是,這項工作已經完成。Python的email軟體包非常擅長此任務。
請記住,我們已經較早匯入了該軟體包。現在,我們將其message_from_string()功能應用於item,以將完整的電子郵件轉換為emailMessage物件。Message物件由標頭和有效負載組成,它們分別對應於電子郵件的標頭和正文。
接下來,我們將其get_payload()功能應用於Message物件。此功能隔離電子郵件的正文。我們將其分配給變數body,然後將其插入到emails_dict鍵下的字典中"email_body"。
為什麼使用電子郵件軟體包而不是正文
您可能會問,為什麼使用emailPython軟體包而不是regex?這是因為目前還沒有很好的方法來處理Python正則表示式,而這不需要大量的清理工作。這意味著可能需要另外一份教程。
值得檢查一下我們如何做出這樣的決定。但是,我們需要先了解[ ]正則表示式中的方括號,然後才能這樣做。
現在,我們可以更好地瞭解我們是如何決定使用電子郵件軟體包的。
窺視資料集可發現電子郵件標題在字串"Status: 0"或處停止"Status: R0",並"From r"在下一封電子郵件的字串前結束。因此,我們可以Status:\s*\w*\n*[\s\S]*From\sr*用來僅獲取電子郵件正文。[\s\S]*適用於大塊的文字,數字和標點符號,因為它可以搜尋空白或非空白字元。
不幸的是,有些電子郵件包含多個"Status:"字串,而另一些則不包含"From r",這意味著我們會將電子郵件拆分成多於或少於電子郵件列表中詞典的數量。它們與我們已經擁有的其他類別不匹配。使用熊貓時,這會產生問題。因此,我們決定利用該email軟體包。
建立詞典列表
最後,將字典追加emails_dict到emails列表中:
我們可能要emails在此時列印列表以檢視其外觀。如果您只是一直在使用我們的小樣本檔案,那麼這將是反高潮的,但是在整個語料庫中,您將看到正則表示式的強大功能!
我們還可以print(len(emails_dict))檢視列表中有多少個詞典,因此還有電子郵件。如前所述,整個語料庫包含3977。
這是完整的程式碼:
如果使用我們的示例文字檔案執行它,將會得到以下結果:
我們已經打印出emails列表中的第一項,它顯然是帶有鍵和值對的字典。因為我們使用了for迴圈,所以每個字典都具有相同的鍵但值不同。
我們已替換為item,"email content here"以便我們不會打印出電子郵件的全部內容並阻塞螢幕。如果您要使用實際資料集在家列印此檔案,則會看到整個電子郵件。
用熊貓處理資料
有了列表中的詞典,我們使熊貓圖書館的工作變得無比輕鬆。每個鍵將成為列標題,每個值將成為該列中的一行。
我們要做的就是應用以下程式碼:
透過這一行,我們emails使用pandas DataFrame()函式將字典列表轉換為資料框。我們也將其分配給變數。
而已。現在,我們有了一個複雜的熊貓資料框。這實際上是一個整潔的表格,其中包含我們從電子郵件中提取的所有資訊。
讓我們看一下前幾行。
該dataframe.head()函式僅顯示前幾行,而不顯示整個資料集。這需要一個論點。一個可選引數允許我們指定要顯示多少行。在這裡,n=3讓我們檢視三行。
我們還可以精確地找到我們想要的東西。例如,我們可以找到從特定域名傳送的所有電子郵件。但是,讓我們學習一種新的正則表示式模式,以提高找到所需專案的精度。
管道符號會|在其任一側尋找字元。例如,a|b尋找a或b。
|可能看起來與相同[ ],但是它們確實有所不同。假設我們要匹配要麼"crab","lobster"或"isopod"。大資料分析Python的正則表示式Regular Expressions使用方法https://www.aaa-cg.com.cn/data/2301.html使用crab|lobster|isopod會比有意義[crablobsterisopod],不是嗎?前者將尋找每個單詞,而後者將尋找每個字母。
現在,我們|來查詢從一個或另一個域名傳送的所有電子郵件。
我們在這裡使用了相當長的程式碼。讓我們從內而外開始。
emails_df["sender_email"]選擇標記為的列sender_email。接下來,str.contains(epatra|spinfinder)返回True是否在該列中找到子字串"epatra"或"spinfinder"。最後,外部emails_df[]返回行的檢視,其中該sender_email列包含目標子字串。好漂亮!
我們也可以檢視來自各個單元的電子郵件。為此,我們經歷了四個步驟。在步驟1中,我們找到"sender_email"列包含字串的行的索引"@spinfinder"。注意我們如何使用正則表示式來執行此操作。
在步驟2中,我們使用索引查詢電子郵件地址,該loc[]方法作為具有多個不同屬性的Series物件返回該電子郵件地址。我們在下面將其打印出來以檢視其外觀。
在第3步中,我們從系列物件中提取電子郵件地址,就像從列表中提取專案一樣。您可以看到它的型別現在是class。
步驟4是提取電子郵件正文的位置。
在步驟4中,emails_df["sender_email"] == "[email protected]"找到該sender_email列包含value 的行"[email protected]"。接下來,["email_body"].values查詢email_body同一行中的列的值。最後,我們打印出該值。
如您所見,我們可以透過多種方式使用正則表示式,它也可以與大熊貓一起使用!如果您的正則表示式工作包含大量的反覆試驗,請不要氣,,尤其是在您剛剛入門時!
其他資源
自從幾年前正則表示式從生物學躍升為工程學以來,正則表示式已取得了巨大的發展。如今,正則表示式已在不同的程式語言中使用,其中除了其基本模式之外還有一些變體。我們已經學習了很多Python正則表示式,並且如果您想將它提高到一個新的水平,那麼我們的Python資料清理高階課程可能是一個不錯的選擇。
您還可以在官方參考資料中找到一些幫助,例如Python 有關其模組的文件re。Google有更快的參考資料。
如果您願意,也可以開始探索Python regex與其他形式的regex Stack Overflow帖子之間的區別。
如果您需要資料集進行試驗,則Kaggle和StatsModels很有用。
最後,這是我們製作的Regex速查表,它也非常有用。
https://www.toutiao.com/i6829923957647344142/
回覆列表
swift不支援命名的分組捕獲,只支援由()括起來表示的匿名分組捕獲 蘋果官方Reference裡的Regular Expression Operators一節,明確寫出了支援的表示式算符,其中不包括<> 但包括以下: (...) Capturing parentheses. Range of input that matched the parenthesized subexpression is available after the match.