उत्तर देने योग्य: किसी सूची को उसके गुण द्वारा फ़िल्टर करें


84

मेरे पास "नेटवर्क" नाम का वेरिएबल है जो अंसिबल में पंजीकृत है:

{
    "addresses": {
        "private_ext": [
            {
                "type": "fixed",
                "addr": "172.16.2.100"
            }
        ],
        "private_man": [
            {
                "type": "fixed",
                "addr": "172.16.1.100"
            },
            {
                "type": "floating",
                "addr": "10.90.80.10"
            }
        ]
    }
}

क्या आईपी एड्रेस ("एड्र") टाइप = "फ्लोटिंग" के साथ ऐसा कुछ करना संभव है?

- debug: var={{ network.addresses.private_man | filter type="fixed" | get "addr" }}

मुझे पता है कि वाक्य रचना गलत है, लेकिन आपको विचार मिलता है।

जवाबों:


41

मैं एक सबमिट करने के बाद पुल अनुरोध (Ansible 2.2+ में उपलब्ध है) कि जोड़कर आसान स्थितियों के इस प्रकार के कर देगा jmespath Ansible पर क्वेरी समर्थन करते हैं। आपके मामले में यह काम करेगा:

- debug: msg="{{ addresses | json_query(\"private_man[?type=='fixed'].addr\") }}"

लौटूंगा:

ok: [localhost] => {
    "msg": [
        "172.16.1.100"
    ]
}

3
Json_query फ़िल्टर को चलाने से पहले आपको "jmespath" इंस्टॉल करना होगा।
ceving

और मैंने अभी पायथन संस्करण के मतभेदों के कारण जेमस्पाथ स्थापित करने की कोशिश की। यह ट्रिवियल सॉल्यूशन के रूप में नहीं है क्योंकि यह आंसिबल 2.4+ पर दिखता है
स्टुअर्ट वाट

1
@StuartWatt आपको ऑपरेटिंग सिस्टम पाइथन संस्करण से खुद को दूर करने के लिए pyenv की आवश्यकता हो सकती है। आप pyenv, pyenv virtualenvs, या कुछ लोग pipenv पसंद कर सकते हैं। वे सभी समान काम करेंगे।
16

@Jepper यदि आपको Ansible का उपयोग करने के लिए एक पूरे नए पायथन की आवश्यकता है, तो यह एक हारी हुई लड़ाई है। (और मैं pyenv का उपयोग कर रहा था और अभी भी ये मुद्दे थे :-)
स्टुअर्ट वाट

128

डक्ट्स की सूची को फ़िल्टर करने के लिए आप समान टेस्ट के साथ चयनकर्ता फ़िल्टर का उपयोग कर सकते हैं :

network.addresses.private_man | selectattr("type", "equalto", "fixed")

इसके बाद के संस्करण की आवश्यकता है जिन्जा 2 v2.8 या बाद में (विचारणीय संस्करण की परवाह किए बिना)।


अन्सिबल के परीक्षणmatchsearch भी हैं और , जो नियमित अभिव्यक्ति लेते हैं:

matchस्ट्रिंग में एक पूर्ण मैच searchकी आवश्यकता होगी , जबकि स्ट्रिंग के अंदर एक मैच की आवश्यकता होगी।

network.addresses.private_man | selectattr("type", "match", "^fixed$")

डिकोट्स की सूची को स्ट्रिंग्स की सूची में कम करने के लिए, इसलिए आपको केवल addrफ़ील्ड्स की एक सूची मिलती है , आप मैप फ़िल्टर का उपयोग कर सकते हैं :

... | map(attribute='addr') | list

या यदि आप एक अल्पविराम से अलग स्ट्रिंग चाहते हैं:

... | map(attribute='addr') | join(',')

संयुक्त, यह इस तरह दिखेगा।

- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}

1
यदि आप उन्हें कॉमा से अलग किए गए स्ट्रिंग के बजाय एक सूची के रूप में चाहते हैं, तो आप भी उपयोग कर सकते हैं:{{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | list }}
TrinitronX

1
क्या आपने लिंक प्रदान किया है? मैं उस पृष्ठ पर "मैच" और "खोज" नहीं पा सकता
हूं

1
@activedecay ऐसा लगता है कि यह उस पृष्ठ से चला गया है, हाँ। एकमात्र उल्लेख जो मुझे अब मिल सकता है वह इस पृष्ठ पर है: docs.ansible.com/ansible/latest/user_guide/… मैंने लिंक को अपडेट किया, धन्यवाद!
32ूदान

19

जरूरी नहीं कि बेहतर हो, लेकिन चूँकि यहाँ विकल्पों के बारे में जानना अच्छा है कि जिन्ना के बयानों का उपयोग कैसे किया जाए :

- debug:
    msg: "{% for address in network.addresses.private_man %}\
        {% if address.type == 'fixed' %}\
          {{ address.addr }}\
        {% endif %}\
      {% endfor %}"

या यदि आप इसे एक पंक्ति में रखना पसंद करते हैं:

- debug:
    msg: "{% for address in network.addresses.private_man if address.type == 'fixed' %}{{ address.addr }}{% endfor %}"

कौन सा रिटर्न:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.