最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Swift?中的?RegexBuilder學(xué)習(xí)指南

 更新時間:2023年04月07日 10:47:43   作者:馮志浩  
這篇文章主要為大家介紹了Swift中的RegexBuilder學(xué)習(xí)指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

在我們?nèi)粘5捻椖块_發(fā)中,經(jīng)常會碰到和正則表達(dá)式打交道的時候。比如用戶密碼,通常會要求同時包含小寫字母、大寫字母、數(shù)字,并且長度不少于 8 位,以此來提高密碼的安全性。

在 Swift 中,我們可以用正則表達(dá)式的字面量方式來進(jìn)行實現(xiàn)。

Regex 字面量

Regex 字面量實現(xiàn)代碼:

let regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/
let text = "Aa11111111"
print(text.matches(of: regex).first?.output) // Optional("Aa11111111")

通過上述代碼可以看到,//通過兩個斜線就可以來生成正則的字面量。用字面量的方式確實可以使代碼很簡潔,但簡潔的代價就是很難看懂,對后面的代碼維護(hù)也造成了很大的困難。

就像網(wǎng)上盛傳的一句梗一樣:“我有一個問題,所以我寫了一個正則表達(dá)式。現(xiàn)在,我有了兩個問題。”??

對于 Regex 難懂且難維護(hù)的問題,Swift 的開發(fā)團(tuán)隊給出的方案就是:RegexBuilder。

RegexBuilder - 像寫代碼一樣寫正則

假設(shè)我們有一個字符串"name: John Appleseed, user_id: 100",想要提取其中user_id的值。 首先第一步,先導(dǎo)入 RegexBuilder:

import RegexBuilder

接著,通過結(jié)構(gòu)體 Regex 來構(gòu)建正則語句:

let regex = Regex {
    "user_id:" // 1
    OneOrMore(.whitespace) // 2
    Capture(.localizedInteger(locale: Locale(identifier: "zh-CN"))) // 3
}

第一行代碼匹配的是固定字符串:"user_id",第二行代碼匹配的是一個或者多個空格,第三行代碼則是匹配的整型數(shù)字。

localizedInteger 會將匹配到的數(shù)字自動轉(zhuǎn)為整型,比如下面的例子:

let input = "user_id:  100.11"
let regex = Regex {
    Capture(.localizedInteger(locale: Locale(identifier: "zh-CN")))
}
if let match = input.firstMatch(of: regex) {
    print("Matched: \(match.0)") // Matched:  100.11
    print("User ID: \(match.1)") // User ID: 100
}

雖然匹配的是 100.11,但輸出的仍然是 100。

最后,就可以通過 macth 的相關(guān)函數(shù)來進(jìn)行數(shù)據(jù)提取了:

if let match = input.firstMatch(of: regex) {
    print("Matched: \(match.0)")
    print("User ID: \(match.1)")
}

RegexRepetitionBehavior

該結(jié)構(gòu)體是用來定義匹配的重復(fù)行為的,它有三個值:

  • edger:會盡可能多的去匹配輸入的字符,必要的時候會回溯。默認(rèn)為edger
  • reluctant:會盡可能少的去匹配輸入的字符,它會根據(jù)你的需求來一點點增大匹配區(qū)域,以完成匹配。
  • possessive:會盡可能多的去匹配輸入的字符,不會回溯。

比如下面這個例子:

let testSuiteTestInputs = [    "2022-06-06 09:41:00.001",    "2022-06-06 09:41:00.001.",    "2022-06-06 09:41:00.001."]
let regex = Regex {
    Capture(OneOrMore(.any))
    Optionally(".")
}
for line in testSuiteTestInputs {
    if let (dateTime) = line.wholeMatch(of: regex)?.output {
        print("Matched: \(dateTime)\"")
    }
}

因為這三條數(shù)據(jù)最后的.是不一定有的,所以我們的正則有一個 Optionally(".")。但匹配出來的 dateTime 還是會帶 .。因為 edger 會匹配所有的字符包含最后的點在內(nèi),這樣 Optionally(".") 根本不會起作用。

改成 Capture(OneOrMore(.any, .reluctant))則會修復(fù)這個問題。因為 reluctant 它是匹配盡可能少的輸入,所以最后的Optionally(".")會執(zhí)行。

在 Swift 5.7 中,F(xiàn)oundation 框架也對 RegexBuilder 進(jìn)行適配。所以對于 Date、URL等類型,我們可以借助 Foundation 的強(qiáng)大功能來進(jìn)行解析。

Foundation 的支持

假如,我們在做一個金融相關(guān)的 APP,為了兼容一些老數(shù)據(jù),需要將一些字符串類型的數(shù)據(jù)轉(zhuǎn)為結(jié)構(gòu)體。

這是我們的字符串?dāng)?shù)據(jù):

let statement = """
CREDIT    2022/03/03    張三     ¥2,000,000.00
DEBIT     03/03/2022    Tom      $2,000,000.00
DEBIT

這是我們需要轉(zhuǎn)的結(jié)構(gòu)體:

struct Trade {
    let type: String
    let date: Date
    let name: String
    let count: Decimal
}

下面這個就是我們需要編寫的 Regex:

let regex = Regex {
    Capture {
        /CREDIT|DEBIT/
    }
    OneOrMore(.whitespace)
    Capture {
        One(.date(.numeric, locale: Locale(identifier: "zh_CN"), timeZone: .gmt))
    }
    OneOrMore(.whitespace)
    Capture {
        OneOrMore(.word)
    }
    OneOrMore(.whitespace)
    Capture {
        One(.localizedCurrency(code: "CNY", locale: Locale(identifier: "zh_CN")))
    }
}

首先,我們需要匹配固定的字符串:CREDIT/DEBIT,接著是匹配一個或者多個空格。

接下來就是 Foundation 的重頭戲了,對于日期類型的字符串,我們并不需要寫一些匹配年月日規(guī)則的正則,只需要借助 Foundation 內(nèi)嵌的功能即可。這樣做不僅省去了我們自己編寫的時間,更重要的是:官方寫的要比我們自己寫的更能保證代碼的正確性。

需要注意的是,Apple 推薦我們顯式的寫出 locale 屬性,而不是下面這種跟隨系統(tǒng)寫法 :

?

One(.date(.numeric, locale: Locale.current, timeZone: TimeZone.current))

因為這種寫法會帶來多種預(yù)期,并不能保證數(shù)據(jù)的確定性。

匹配完日期,接著就是對空格和用戶名的匹配。最后,是對交易金額的匹配,金額也是 Foundation 提供的函數(shù)來進(jìn)行的匹配。

測試代碼:

let result = statement.matches(of: regex)
var trades = [Trade]()
result.forEach { match in
    let (_, type, date, name, count) = match.output
    trades.append(Trade(type: String(type), date: date, name: String(name), count: count))
}
print(trades) 
// [SwiftDemo.Trade(type: "CREDIT", date: 2022-03-03 00:00:00 +0000, name: "張三", count: 2000000), SwiftDemo.Trade(type: "DEBIT", date: 2022-03-05 00:00:00 +0000, name: "李三", count: 33.27)]

通過打印可以得知,輸出的結(jié)果并不符合預(yù)期,漏掉了 Tom 那條數(shù)據(jù)。漏掉的原因可以通過代碼一眼得知:因為對日期和金額我們顯式的指定了是中國的格式,顯然03/03/2022 這種格式是不符合年月日的格式的。這也體現(xiàn)了顯式指定格式的好處:方便排查問題。

我們只要將日期格式轉(zhuǎn)為年月日格式,再將 $ 轉(zhuǎn)為 ¥ 即可讓正則正確匹配。

首先,我們需要根據(jù) currency 來來返回正確的 Date 類型:

func pickStrategy(_ currency: Substring) -> Date.ParseStrategy {
  switch currency {
  case "$": return .date(.numeric, locale: Locale(identifier: "en_US"), timeZone: .gmt)
  case "¥": return .date(.numeric, locale: Locale(identifier: "zh_CN"), timeZone: .gmt)
  default: fatalError("We found another one!")
  }
}

接著,編寫正則表達(dá)式來獲取相應(yīng)的字符串字段:

let regex1 = #/
  (?<date>     \d{2} / \d{2} / \d{4})
  (?<name>   \P{currencySymbol}+)
  (?<currency> \p{currencySymbol})
/#

注:#//#格式為 Swift 中運行時正則表達(dá)式的格式。

最后,再調(diào)用 replace 函數(shù)來進(jìn)行符合正則的字符替換:

statement.replace(regex1) { match -> String in
    print(match.currency)
    let date = try! Date(String(match.date), strategy: pickStrategy(match.currency))
    // ISO 8601, it's the only way to be sure
    let newDate = date.formatted(.iso8601.year().month().day())
    return newDate + match.name + "¥"
  }
statement = statement.replacingOccurrences(of: "-", with: "/")

這樣,我們就能解析出符合我們需求的 Trade 類型的數(shù)據(jù)了。

總結(jié)

  • RegexBuilder 會使代碼更加易讀易維護(hù)
  • RegexRepetitionBehavior 的三個值的區(qū)別
  • 盡可能多的使用 Foundation 提供的函數(shù)來解析數(shù)據(jù)
  • 使用 Foundation 時要指定格式解析數(shù)據(jù),這樣可以保證數(shù)據(jù)的唯一性

參考鏈接

以上就是Swift 中的 RegexBuilder學(xué)習(xí)指南的詳細(xì)內(nèi)容,更多關(guān)于Swift RegexBuilder的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談Swift編程中switch與fallthrough語句的使用

    淺談Swift編程中switch與fallthrough語句的使用

    這篇文章主要介紹了Swift編程中switch與fallthrough語句的使用,用于基本的流程控制,需要的朋友可以參考下
    2015-11-11
  • Swift自動調(diào)整視圖布局AutoLayout和AutoresizingMask功能詳解

    Swift自動調(diào)整視圖布局AutoLayout和AutoresizingMask功能詳解

    這篇文章主要為大家介紹了Swift自動調(diào)整視圖布局AutoLayout和AutoresizingMask功能及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Swift 數(shù)組及常用方法詳解總結(jié)

    Swift 數(shù)組及常用方法詳解總結(jié)

    數(shù)組(Array)是有序的元素序列。 若將有限個類型相同的變量的集合命名,那么這個名稱為數(shù)組名。組成數(shù)組的各個變量稱為數(shù)組的分量,也稱為數(shù)組的元素,有時也稱為下標(biāo)變量
    2021-11-11
  • swift實現(xiàn)簡單的計算器

    swift實現(xiàn)簡單的計算器

    這篇文章主要為大家詳細(xì)介紹了swift實現(xiàn)簡單的計算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Swift學(xué)習(xí)教程之訪問控制詳解

    Swift學(xué)習(xí)教程之訪問控制詳解

    訪問控制可以限定你在源文件或模塊中訪問代碼的級別,也就是說可以控制哪些代碼你可以訪問,哪些代碼你不能訪問。下面這篇文章主要給大家介紹了關(guān)于Swift學(xué)習(xí)教程之訪問控制的相關(guān)資料,需要的朋友可以參考下。
    2017-08-08
  • Swift實現(xiàn)簡易計算器功能

    Swift實現(xiàn)簡易計算器功能

    這篇文章主要為大家詳細(xì)介紹了Swift實現(xiàn)簡易計算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Swift中switch語句區(qū)間和元組模式匹配

    Swift中switch語句區(qū)間和元組模式匹配

    這篇文章主要介紹了Swift中switch語句區(qū)間和元組模式匹配的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12
  • Swift開發(fā)中switch語句值綁定模式

    Swift開發(fā)中switch語句值綁定模式

    本文給大家分享Swift開發(fā)中switch語句值綁定模式,非常不錯,具有參考借鑒價值,需要的的朋友參考下
    2016-12-12
  • 深入理解Swift中的訪問控制關(guān)鍵字

    深入理解Swift中的訪問控制關(guān)鍵字

    這篇文章主要給大家介紹了Swift中訪問控制關(guān)鍵字的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • swift5.3 UIColor使用十六進(jìn)制顏色的方法實例

    swift5.3 UIColor使用十六進(jìn)制顏色的方法實例

    這篇文章主要給大家介紹了關(guān)于swift5.3 UIColor使用十六進(jìn)制顏色的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評論

疏附县| 开鲁县| 陕西省| 文登市| 施秉县| 清水县| 砀山县| 郓城县| 上蔡县| 铅山县| 涞水县| 怀柔区| 孙吴县| 杭州市| 岳阳县| 区。| 睢宁县| 封丘县| 松潘县| 乌拉特前旗| 手游| 富蕴县| 赤峰市| 梨树县| 唐河县| 玉环县| 兴义市| 吴川市| 五峰| 双桥区| 政和县| 上蔡县| 石林| 上栗县| 安康市| 兰坪| 和龙市| 资阳市| 会宁县| 扎赉特旗| 益阳市|