小技巧 - 取得字串中指定的部份

有些時候,會需要取得字串中的某個部份來使用,這時候可以怎麼做呢?

場景1:知道需要的部份在固定的位置

這種情況很簡單,就用 [start:end:step] 來處理就可以,如果你熟悉 Python 的話會覺得很熟悉。基本上這裡的用法就跟 Python 處理字串的用法是一樣的。

[-2:] ,表示是字串最後兩個字元;[3:6] 表示是字串裡第四個字元到第六個字元,[0:2][:2] 都表示是取字串前面兩個字元。

---
# test-substring.yaml
# ansible-playbook -i localhost, -c local test-substring.yaml
- name: Get substring
  hosts: all

  vars:
    content: "01234567890"

  tasks:
    - name: Get substring
      set_fact:
        new_content_1: "{{ content[-2:] }}"
        new_content_2: "{{ content[3:6] }}"
    - name: Display
      debug:
        msg: "new_content_1={{ new_content_1 }} new_content2={{ new_content_2 }}"

執行結果

TASK [Display] *****************************************************************
ok: [localhost] => {
    "msg": "new_content_1=90 new_content2=345"
}

場景2:字串位置不一定,但是有規則可循

這種情況可以利用 regular expression 的 group 來處理,Ansible 的文件有提到這部份:Searching strings with regular expressions

摹擬情境如下,現在有個字串是 “/opt/jboss/MyApps/installedApps/OrzXD.ear/XDWeb.war/WEB-INF/classes/",想要取出 “Orz” 跟 “.ear” 中間的字串,還有 “/” 跟 “Web.war” 中間的字串,那麼就可以這樣寫。

---
# test-regex_search.yaml
# ansible-playbook -i localhost, -c local test-regex_search.yaml
- name: Test regex_search
  hosts: all

  vars:
    content: "/opt/jboss/MyApps/installedApps/OrzXD.ear/XDWeb.war/WEB-INF/classes/"

  tasks:
  - name: Use regex_search
    set_fact:
      result1: "{{ content | regex_search('\\/opt\\/jboss\\/MyApps\\/installedApps\\/Orz(.+).ear\\/(.+)Web.war\\/WEB-INF\\/classes\\/', '\\1') | first }}"
      result2: "{{ content | regex_search('\\/opt\\/jboss\\/MyApps\\/installedApps\\/Orz(.+).ear\\/(.+)Web.war\\/WEB-INF\\/classes\\/', '\\2') | first }}"

  - debug:
      var: result1

  - debug:
      var: result2

說明:

  1. "\\/opt\\/jboss\\/MyApps\\/installedApps\\/Orz(.+).ear\\/(.+)Web.war\\/WEB-INF\\/classes\\/" 這個字串是描述規則,表示要把符合這規則的字串找出來。
  2. 有括號括起來的地方 (.+) ,表示是 group,要擷取出來的部份。
  3. 在 regular expression 裡,/ 表示搜尋,但因為是路徑,我們不需要被認定為搜尋,所以在 / 前面加上 \\ 來告知要把 / 處理為正常的 / ,而非搜尋。

執行結果如下

TASK [debug] **********************************************************************************************************************
ok: [localhost] => {
    "result1": "XD"
}

TASK [debug] **********************************************************************************************************************
ok: [localhost] => {
    "result2": "XD"
}

以上介紹了兩種可以取得部份字串的方法,希望對大家有幫助。

參考資料