Ansible Filter滤波器的使用(一)

news2024/12/29 10:50:53

一、【说在前面】

Ansible Filter一般被称为滤波器或者叫过滤器。

这个东西初次听到以为是什么科学计算的东西,但是想来ansible不太可能有什么滤波操作,所以这个东西本质是一个数值筛选器,内置函数,本质是一个为了做区别化的工具,比如根据不同的机器名做不同操作,根据预先设定的值做区别化对待。

这篇文章介绍一下ansibe常用的过滤器是怎么用的,有什么作用,官网文档更详细,但看起来例子比较单薄,本文本质是笔者回顾Ansible的学习笔记,希望这篇文章能发挥一些补充作用。

官网:Using filters to manipulate data — Ansible Documentation

二、【常用过滤器介绍】

1. 默认过滤器 (default filter):

这个过滤器用于为变量指定默认值,或者叫缺省值,这种方法可以为剧本添加某个默认动作。这里以debug打印数值为例。

---
- hosts: localhost
  gather_facts: no
  vars:
    # 模拟一个有时有值,有时没有值的变量
    my_variable_present: "I have a value"
    my_variable_absent: null  # 或者可以将这个变量设置为 ""

  tasks:
    - name: Set default value if variable is absent
      set_fact:
        # 使用 default 过滤器,如果变量不存在或者为空,将其设置为默认值 "Default Value"
        my_variable_present: "{{ my_variable_present | default('Default Value') }}"
        my_variable_absent: "{{ my_variable_absent | default('Default Value') }}"

    - debug:
        var: my_variable_present
    - debug:
        var: my_variable_absent

2. 省略参数 (omit parameter):

这个功能结合默认过滤器用于省略模块参数。

---
# 定义主机为 localhost,这表示剧本将在本地主机上执行。
- hosts: localhost

  # 不收集主机的事实信息,因为此剧本只操作变量而不需要主机信息。
  gather_facts: no

  # 定义变量部分,这里创建了两个变量,一个有值,一个没有值。
  vars:
    file_path_present: "/path/to/existing/file.txt"
    file_path_absent: null  # 或者可以将这个变量设置为 ""

  # 任务部分,包含两个任务。
  tasks:

    # 第一个任务名称,用于创建一个文件,如果变量 file_path_present 存在。
    - name: Create a file if path is provided
      file:
        # 使用 default 过滤器和 omit 变量,以便在 file_path_present 存在时,设置 path 参数。
        path: "{{ file_path_present | default(omit) }}"
        state: touch
      when: file_path_present is defined

    # 第二个任务名称,用于创建一个文件,如果变量 file_path_absent 不存在。
    - name: Create a file with omitted path
      file:
        # 使用 default 过滤器和 omit 变量,以便在 file_path_absent 不存在时,省略 path 参数。
        path: "{{ file_path_absent | default(omit) }}"
        state: touch
      when: file_path_absent | default(omit) is omit

3. 集合或列表过滤器 (set theory or list filters):

这些过滤器用于操作列表变量。有常见的什么集合、去重操作之类。

---
- hosts: localhost
  gather_facts: no
  vars:
    list1: [1, 2, 5, 1, 3, 4, 10]
    list2: [1, 2, 3, 4, 5, 11, 99]
  tasks:
    - name: Get a unique set from list1
      debug:
        var: list1 | unique  # 做一个unique操作,去重用
    - name: Get the union of list1 and list2
      debug:
        var: list1 | union(list2) # 这是做list1和list2的并集
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
# => [1, 2, 5, 1, 3, 4, 10, 11, 99]


    - name: Get the intersection of list1 and list2
      debug:
        var: list1 | intersect(list2) # 求一个交集
# list1: [1, 2, 5, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
# => [1, 2, 5, 3, 4]


    - name: Get the difference of list1 and list2
      debug:
        var: list1 | difference(list2) # 这是拿出list1中有,list2没有的值,也即差集
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
# => [10]

    - name: Get the symmetric difference of list1 and list2
      debug:
        var: list1 | symmetric_difference(list2) # 对称差集,没有同时存在的值
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
# => [10, 11, 99]

4. 三元表达式(ternary): 

本质是一个快速判断的工具,用于快速判断一个表达式,用法是:

{{ condition | ternary(true_value, false_value) }}

---
- hosts: localhost
  gather_facts: no
  vars:
    status: "needs_restart"
    enabled: true
    some_value: null

  tasks:

    # 第一个任务:检查状态并确定动作
    - name: Check the status and determine action
      debug:
        msg: |
          # 打印状态值和相应的动作
          Status is "{{ status }}". Action: {{
          (status == 'needs_restart') | ternary('Restart', 'Continue') }}

    # 第二个任务:检查是否已启用并配置
    - name: Check if enabled and configure
      debug:
        msg: |
          # 打印是否已启用和相应的配置
          Enabled: "{{ enabled }}". Configuration: {{
          enabled | ternary('No Shutdown', 'Shutdown') }}

    # 第三个任务:检查一个值并处理空值
    - name: Check a value and handle null
      debug:
        msg: |
          # 打印某个值和根据是否为null选择的结果
          Some Value: "{{ some_value }}". Result: {{
          some_value | ternary('Not Null', 'Null') }}
 

5. 发现数据类型(Discovering the data type)

这是 Ansible 2.3 版本中引入的功能。如果您不确定一个变量的底层 Python 数据类型是什么,您可以使用 ansible.builtin.type_debug 过滤器来显示它。这在调试过程中非常有用

---
- hosts: localhost
  gather_facts: no
  vars:
    # 定义一个变量,包含不同数据类型的值
    myvar_string: "This is a string"
    myvar_integer: 42
    myvar_list: [1, 2, 3]
    myvar_dict: {"key": "value"}
  
  tasks:
    - name: Display the data type of variables
      debug:
        # 使用 type_debug 过滤器显示变量的数据类型
        msg: "myvar_string: {{ myvar_string | type_debug }}, myvar_integer: {{ myvar_integer | type_debug }}, myvar_list: {{ myvar_list | type_debug }}, myvar_dict: {{ myvar_dict | type_debug }}"

6. 字典过滤器 (dictionary filters):

包括 dict2items 过滤器,它将字典转换为项目列表,以及 items2dict 过滤器,反之亦然。

---
- hosts: localhost
  gather_facts: no
  vars:
    # 定义一个字典变量
    my_dict:
      users: /etc/passwd
      groups: /etc/group
  
  tasks:
    - name: Transform dictionary into a list of items
      debug:
        # 使用 dict2items 过滤器将字典转换为项列表
        msg: "{{ my_dict | dict2items }}"
# 会把这个字典平铺成一个列表。会变成
# - file: users
#   path: /etc/passwd
# - file: groups
#   path: /etc/group

7. 生成yaml或json(Formatting data: YAML and JSON):

这个过滤器一共就是六个语句:to_yaml, to_json, to_nice_yaml, to_nice_json;以及from_json, from_yaml

nice不nice取决于可读性的好坏,并且这四种都可以设置每行缩进和每行长度限制

---
- hosts: localhost
  gather_facts: no
  vars:
    # 定义一个字典变量
    my_dict:
      name: "John"
      age: 30
      city: "New York"
      hobbies:
        - Reading
        - Hiking
        - Cooking
  
  tasks:

    # 第一个任务:将字典转换为JSON格式并显示
    - name: Convert to JSON format
      debug:
        msg: |
          # 使用 to_json 过滤器将 my_dict 转换为JSON格式的字符串
          JSON Format:
          {{ my_dict | to_json(indent=8, width=1337) }} # 设置每行缩进8,宽度限制1337
    
    # 第二个任务:将字典转换为YAML格式并显示
    - name: Convert to YAML format
      debug:
        msg: |
          # 使用 to_yaml 过滤器将 my_dict 转换为YAML格式的字符串
          YAML Format:
          {{ my_dict | to_yaml }}
    
    # 第三个任务:将字典转换为格式化良好的JSON格式并显示
    - name: Convert to Nice JSON format
      debug:
        msg: |
          # 使用 to_nice_json 过滤器将 my_dict 转换为格式化良好的JSON格式的字符串
          Nice JSON Format:
          {{ my_dict | to_nice_json }}
    
    # 第四个任务:将字典转换为格式化良好的YAML格式并显示
    - name: Convert to Nice YAML format
      debug:
        msg: |
          # 使用 to_nice_yaml 过滤器将 my_dict 转换为格式化良好的YAML格式的字符串
          Nice YAML Format:
          {{ my_dict | to_nice_yaml }}

# 在写一个使用from_json的例子:
tasks:
  - name: Register JSON output as a variable
    ansible.builtin.shell: cat /some/path/to/file.json
    register: result

  - name: Set a variable
    ansible.builtin.set_fact:
      myvar: "{{ result.stdout | from_json }}"

8. Zip 和 Zip_Longest 过滤器(Combining items from multiple lists: zip and zip_longest):

这些过滤器用于合并多个列表的元素,可以选择填充间隙,跟python内置方法zip差不多。

---
- hosts: localhost
  gather_facts: no
  vars:
    # 定义多个列表
    list1: [1, 2, 3, 4, 5]
    list2: ['a', 'b', 'c', 'd']
    list3: ['x', 'y']

  tasks:

    # 使用 zip 过滤器将两个列表组合成一个新列表
    - name: Combine two lists using zip
      debug:
        msg: |
          # 使用 zip 过滤器将 list1 和 list2 组合成新列表,生成长度与短的列表一致
          Combined List:
          {{ list1 | zip(list2) | list }}
          # [[1, "a"], [2, "b"], [3, "c"], [4, "d"]]
    
    # 使用 zip_longest 过滤器将三个列表组合成一个新列表,并用 'X' 填充不足的元素
    - name: Combine three lists using zip_longest
      debug:
        msg: |
          # 使用 zip_longest 过滤器将 list1、list2 和 list3 组合成新列表,用 'X' 填充不足的元素
          Combined List with Fillvalue 'X':
          {{ list1 | zip_longest(list2, list3, fillvalue='X') | list }}
          # [[1, "a", "x"], [2, "b", "y"], [3, "c", "X"], [4, "d", "X"], [5, "X", "X"]]
    

9. 子元素过滤器 (Combining objects and subelements):

过滤器产生一个对象和该对象的子元素值的乘积,适用于处理嵌套数据结构。

---
- name: Manage SSH Authorized Keys
  hosts: your_target_host
  vars:
    users:
      - name: alice
        authorized_keys:
          - /path/to/alice/key1.pub
          - /path/to/alice/key2.pub
        groups:
          - admin
          - developer
      - name: bob
        authorized_keys:
          - /path/to/bob/key.pub
        groups:
          - developer

  tasks:
    - name: Set authorized SSH keys for each user and group
      ansible.posix.authorized_key:
        user: "{{ item.0.name }}" # 这里对应第零个元素,正好是name
        key: "{{ lookup('file', item.1) }}" 
# 这里索引第一个元素,正好是公钥路径,然后ansible将loop写在后方,
# 会把这个过程重复,剧本将使用ansible.posix.authorized_key模块
# 来确保这些密钥被添加到相应用户的~/.ssh/authorized_keys文件中
        state: present
      loop: "{{ users | subelements('authorized_keys') }}"

10. 组合过滤器(Combining):

这个可以用来组合字典、列表、yaml,本质是数值的混合和替换,已有的值会被替换,没有的值会被混合。主要关注其两个参数recursive and list_merge

  • recursive 是一个布尔值,翻译为递归,默认为 False。它确定是否应递归合并嵌套的哈希。请注意:它不依赖于 ansible.cfg 中的 hash_behaviour 设置。

这个是什么意思呢,也就是说如果我们把这个参数置TRUE,那么对于具有多层级的数据,会对每一层做处理,而设置为FALSE只会做单纯的替换,这里举一个例子

# 对于这个数据,它们的结构是一样的,
# 我们做combine的时候这个递归recursive会影响合并后的结果
default:
  a:
    x: default_value
    y: default_value
  b:
    - 1
    - 2
patch:
  a:
    y: patch_value
    z: patch_value
  b:
    - 3
    - 4

# 如果 recursive = TRUE
# {{ default | combine(patch, recursive=True) }}
{
  'a': {
    'x': 'default_value',
    'y': 'patch_value',
    'z': 'patch_value'
  },
  'b': [1, 2, 3, 4]
}

# 如果 recursive = FALSE
# {{ default | combine(patch, recursive=False) }}
{
  'a': {
    'y': 'patch_value',
    'z': 'patch_value'
  },
  'b': [3, 4]
}
  • list_merge 是一个字符串,可以填为 'replace'(默认)、'keep'、'append'、'prepend'、'append_rp' 或 'prepend_rp'。它会决定当要合并的哈希包含数组/列表时 ansible.builtin.combine 的行为,比如是在尾部追加还是头部追加,冲突是以原数据为准还是以新数据为准。

    • 这里是关于 prependappendkeepappend_rpprepend_rplist_merge 参数中的区别:

    • prepend: 当使用 list_merge='prepend' 时,右边哈希中的数组元素将前置到左边哈希中的数组。换句话说,右边的元素会放在左边的元素之前。

    • append: 当使用 list_merge='append' 时,右边哈希中的数组元素将附加到左边哈希中的数组。右边的元素会放在左边的元素之后。

    • keep: 当使用 list_merge='keep' 时,左边哈希中的数组将被保留,右边哈希中的数组将被忽略,不会有合并或更改。

    • append_rp("rp" 意为 "remove present"):当使用 list_merge='append_rp' 时,右边哈希中的数组元素将附加到左边哈希中的数组。但是,左边哈希中与右边哈希中相对应数组中的元素将被删除。

    • prepend_rp:与 append_rp 类似,但右边哈希中的数组元素会前置到左边哈希中的数组,同时删除左边哈希中与右边哈希中相对应数组中的元素。

然后介绍一下这个方法对常见数据的处理结果

### 例子1
{{ {'a':1, 'b':2} | combine({'b':3}) }}
# {'a':1, 'b':3} 结果会更新b的值

### 例子2 说明keep、append、prepend
# 原数据default
a:
  - default
# 新数据patch
a:
  - patch


{{ default | combine(patch, list_merge='keep') }}   # 这里数据会还是defalt
# 答案,keep是保留原状,如果有撞上了的数据,以原来的为主
#a:
#  - default

{{ default | combine(patch, list_merge='append') }}
# 答案,可以看到插入了尾部
#a:
#  - default
#  - patch

{{ default | combine(patch, list_merge='prepend') }}
# 答案可以看到头部插入了
# a:
#  - patch
#  - default

### 例子3
# 原数据
default:
  a:
    - 1
    - 1
    - 2
    - 3
# 新数据
patch:
  a:
    - 3
    - 4
    - 5
    - 5

{{ default | combine(patch, list_merge='append_rp') }}
# 答案,可以看到分支在尾部进行拼接,冲突数据不会二次追加
# a:
#   - 1
#   - 1
#   - 2
#   - 3
#   - 4
#   - 5
#   - 5

{{ default | combine(patch, list_merge='prepend_rp') }}
# 答案,分支数据在头部拼接,冲突数据不会二次追加
# a:
#   - 3
#   - 4
#   - 5
#   - 5
#   - 1
#   - 1
#   - 2

11. 提取器(extract):

它用于从数组或哈希表中选择值。这个过滤器在Ansible的2.1版本中引入。本质是通过映射做数据的提取,这么说会比较抽象,举个例子看看

# 例子1 
{{ [0, 2] | map('extract', ['x', 'y', 'z']) | list }}
# 这个命令会返回['x', 'z'],刚好是【0,2】这个索引对应到后面的值

# 例子2 
{{ ['x', 'y'] | map('extract', {'x': 42, 'y': 31}) | list }}
# 与例1类似,会返回x和y的值,也即[42, 31]

# 例子3 三参数
{{ groups['x'] | map('extract', hostvars, 'ec2_ip_address') | list }}
# extract 过滤器还可以接受第三个参数,用于执行递归查找
# 我们首先从Ansible的 groups 中选择了名为 'x' 的主机组的列表,
# 然后使用 extract 过滤器执行两次查找。
# 首先,它在 hostvars 中查找了这些主机的信息,
# 然后查找了 ec2_ip_address 键的值(ec2是aws对虚拟机的称呼,elastic comp cloud)
# 最终的结果是一个包含了主机组 'x' 中主机的IP地址列表
# 比如这个例子
x:
  hosts:
    host1:
      ec2_ip_address: '192.168.1.101'
    host2:
      ec2_ip_address: '192.168.1.102'
    host3:
      ec2_ip_address: '192.168.1.103'

# 最后会返回['192.168.1.101', '192.168.1.102', '192.168.1.103']


# 例子4 递归查找
{{ ['a'] | map('extract', b, ['x', 'y']) | list }}
# 比如以这个数据为例子
b:
  a:
    x:
      y: 'value_to_extract'
# 他会逐层搜索,直到找到名为a的数据,也即第二行
# 然后接下来,我们再次使用 extract 过滤器,这次从子哈希表中查找键 'x' 下的值。
# 这将返回一个包含键 'y' 的子哈希表。
# 最后,我们再次使用 extract 过滤器,这次从子哈希表中查找键 'y' 下的值,即 'value_to_extract'

# 因此,最终的结果是 ['value_to_extract'],
# 这是从嵌套的数据结构 b 中提取出来的值。
# 这个操作允许你从深层嵌套的数据结构中选择特定的值,
# 而不必手动递归访问每一层。它可以在处理复杂的数据结构时非常有用。

12. 排列、组合、笛卡尔积(permutations,combinationsproducts

这个和python的itertoolbox库是一个功能,输出排列组合和笛卡尔积

# 例子1
# 排列,第一个是返回所有排列
# 第二个是返回所有长度为 3 的排列
- name: Give me the largest permutations (order matters)
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations | list }}"

- name: Give me permutations of sets of three
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations(3) | list }}"

# 例子2
# 这个例子是给出所有长度为 2 的组合

- name: Give me combinations for sets of two
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.combinations(2) | list }}"

# 例子3
# 这个是给出笛卡尔积,笛卡尔积就是所有位置相乘
# 这个例子会返回两个url
- name: Generate multiple hostnames
  ansible.builtin.debug:
    msg: "{{ ['foo', 'bar'] | product(['com']) | map('join', '.') | join(',') }}"
This would result in:

# 返回 { "msg": "foo.com,bar.com" }

13. Json Query过滤器

这个跟日常经常用到的JQ是一样的,用于切出一个巨大的JSON中我们需要的数据,语句逻辑同样也是JMESPath

# 以这个JSON数据为例
{
    "domain": {
        "cluster": [
            {
                "name": "cluster1"
            },
            {
                "name": "cluster2"
            }
        ],
        "server": [
            {
                "name": "server11",
                "cluster": "cluster1",
                "port": "8080"
            },
            {
                "name": "server12",
                "cluster": "cluster1",
                "port": "8090"
            },
            {
                "name": "server21",
                "cluster": "cluster2",
                "port": "9080"
            },
            {
                "name": "server22",
                "cluster": "cluster2",
                "port": "9090"
            }
        ],
        "library": [
            {
                "name": "lib1",
                "target": "cluster1"
            },
            {
                "name": "lib2",
                "target": "cluster2"
            }
        ]
    }
}


# 例子1 拿到所有集群名
- name: Display all cluster names
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query('domain.cluster[*].name') }}"

# 例子2 拿到所有服务名
- name: Display all server names
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query('domain.server[*].name') }}"

# 例子3 提取集群“cluster 1”的端口号
- name: Display all ports from cluster1
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
  vars:
    server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"

# 例子4 显示集群1的所有端口号,并且写到一行用‘,’分割
- name: Display all ports from cluster1 as a string
  ansible.builtin.debug:
    msg: "{{ domain_definition | community.general.json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"


# 例子5
生成一个字典,分别是name和port的hashmap:
- name: Display all server ports and names from cluster1
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
  vars:
    server_name_cluster1_query: "domain.server[?cluster=='cluster1'].{name: name, port: port}"

# 例子6 从集群名开头为server1的机器提取端口号,本质是多了一层字符串处理
- name: Display ports from all clusters with the name starting with 'server1'
  ansible.builtin.debug:
    msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
  vars:
    server_name_query: "domain.server[?starts_with(name,'server1')].port"


# 例子7 从集群名包含server1的机器中提取端口号
- name: Display ports from all clusters with the name containing 'server1'
  ansible.builtin.debug:
    msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
  vars:
    server_name_query: "domain.server[?contains(name,'server1')].port"

另外,一般用Ansible的JQ时,配合`` to_json | from_json `` 过滤器一起使用。

14. 随机过滤器 (random filters):

包括生成随机 MAC 地址或数字的过滤器,提供诸如为随机数字指定范围或步长的功能。跟python的random库一个作用

# 例子1 需要版本大于version 2.6,根据一个前缀生成一串mac地址
"{{ '52:54:00' | community.general.random_mac }}"
# => '52:54:00:ef:1c:03'
Note that if anything is wrong with the prefix string, the filter will issue an error.

# 例子2 需要版本大于version 2.9 根据一个随机数种子生成一个mac
# 随机数种子的好处是可以生成随机但幂等的随机数,也即只要拿到种子就可以控制随机数
"{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}"


# 例子3 在选定范围生成一个数
"{{ ['a','b','c'] | random }}"
# => 'c'

# 例子4 生成一个范围中的随机数,下面这个是0~60随机生成一个,区间是左闭右开
# 生成一个计划任务,比较实用
"{{ 60 | random }} * * * * root /script/from/cron"
# => '21 * * * * root /script/from/cron'

# 例子5 带有步进的随机数生成,步数为10
# 你可以注意到,这个例子中是101,所以包含了100这个数
{{ 101 | random(step=10) }}
# => 70

# 例子6 生成1到101之间(不包括101),每10为一个步长的随机数。
# 第二个表达式是更明确地指定了起始值为1,步长为10。所以它们都会生成诸如1, 11, 21, ... 91这样步长为10的随机数。注意这里区间左闭右开,101是不包括在内的。
{{ 101 | random(1, 10) }}
# => 31
{{ 101 | random(start=1, step=10) }}
# => 51

# 例子7 根据随机数种子生成一个随机数
"{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron"

15. 列表操作过滤器(managing list variables)

提供一些极值查找,列表平铺等操作

# 例1 最小值
{{ list1 | min }}

# 例2 2.11版本中,添加了一个筛选,这里只比较key = val,其他的忽略
{{ [{'val': 1}, {'val': 2, 'other': 'something'}] | min(attribute='val') }}

# 例3 最大值
{{ [3, 4, 2] | max }}

# 例4 待筛选的最大值选取
{{ [{'val': 1}, {'val': 2}] | max(attribute='val') }}

# 例5 2.5版本中新增了一个平铺设置,比较好理解,跟python中的itertools.chain一个效果
{{ [3, [4, 2] ] | flatten }}
# => [3, 4, 2]

# 例6 带层数的平铺,这里是一层,效果比较好理解
{{ [3, [4, [2]] ] | flatten(levels=1) }}
# => [3, 4, [2]]

# 例7 2.11中新增了一个参数skip_nulls,这里不会跳过空值
{{ [3, None, [4, [2]] ] | flatten(levels=1, skip_nulls=False) }}
# => [3, None, 4, [2]]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1388775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

光学 | 联合Ansys Zemax及Lumerical应对AR/VR市场挑战

当前的增强现实和虚拟现实(AR/VR)市场涵盖了广泛的应用趋势,设计人员和各企业在努力寻找非传统解决方案,以满足主流消费者不断变化的需求。 对于AR头戴设备等可穿戴解决方案,设计思路通常源于对小巧轻量化系统的需求&a…

大数据传输慢的真正原因与解决方案

随着企业数据不断增长,大数据传输已成为一项至关重要的任务。然而,许多企业在处理大数据传输时频繁遭遇传输速度慢的问题。本文将深入探讨大数据传输速度慢的根本原因,并提供一些切实有效的解决方案。 大数据传输在企业中的重要性不言而喻&am…

算法竞赛备赛进阶之数位DP训练

数位DP的思想就是对每一位进行DP,计算时记忆化每一位可以有的状态,其作用是减少运算时间,避免重复计算。 数位DP是一种计数用的DP,一般就是要统计一个区间[A,B]内满足一些条件数的个数。 以1e9甚至1e18、1e100的问题为例&#x…

Docker 容器之间的互相通信

Docker容器之间的互相通信 步骤一:创建自定义网络 首先,我们需要创建一个自定义网络,以便容器可以连接到这个网络上,从而实现互相通信。在命令行中执行以下命令: # 创建 docker network create ddz # 查看 docker n…

洛谷 P1523 旅行商简化版【线性dp+npc问题简化版】

原题链接:https://www.luogu.com.cn/problem/P1523 题目背景 欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家、计算机学家的著名问题。现有的算法都没有办法在确定型机器上在多项式时间内求出最优解,但是有…

2024 年企业要增强反脆弱性,IT 能够做什么?

新冠疫情被称为黑天鹅事件,而“黑天鹅”这个词的创造者纳西姆尼古拉斯塔勒布在另一本书《反脆弱:从不确定性中获益》( CSDN博主读书笔记《反脆弱:从不确定性中获益》 )中,则给出了面对随时可能出现的黑天鹅…

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日,玖章算术旗下NineData 云原生智能数据管理平台 (V1.0)正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试,并获得阿里云颁发的产品生态集成认证。 测试结果表明,玖章算术旗下NineData数据管理平台 (V1.0&#xff…

Python源码23:海龟画图turtle画小狗狗

---------------turtle源码集合--------------- Python教程43:海龟画图turtle画小樱魔法阵 Python教程42:海龟画图turtle画海绵宝宝 Python教程41:海龟画图turtle画蜡笔小新 Python教程40:使用turtle画一只杰瑞 Python教程39…

❤ Uniapp使用一(文档和 API 篇)

❤ Uniapp使用一(文档和 API 篇) 一、介绍 uni-app官网:https://uniapp.dcloud.io/api/media/image?idpreviewimage 微信小程序官网:https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html …

使用WAF防御网络上的隐蔽威胁之SQL注入攻击

SQL注入攻击是一种普遍存在且危害巨大的网络安全威胁,它允许攻击者通过执行恶意的SQL语句来操纵或破坏数据库。 这种攻击不仅能够读取敏感数据,还可能用于添加、修改或删除数据库中的记录。因此,了解SQL注入攻击的机制及其防御策略对于保护网…

Spring基于AOP(面向切面编程)开发

概述 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容&…

使用WAF防御之网络上的隐蔽威胁(XSS攻击)

跨站脚本攻击(XSS)是一种常见且危险的威胁。它允许攻击者在用户浏览器上执行恶意脚本,窃取信息、篡改网页内容,甚至劫持用户会话。 什么是XSS攻击 定义:XSS攻击是一种代码注入技术,攻击者通过在目标网站上…

练习题 删除链表的倒数第N个结点

题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5]示例 2: 输入:head [1], n 1 输出:[]示例 3&#…

潍坊数字孪生元宇宙赋能智能制造,助力工业制造业数字化转型

潍坊工业元宇宙数字孪生赋能智能制造,助力工业制造业数字化转型。在当今数字化时代,工业智能制造已成为制造业发展的必然趋势。潍坊市作为山东省的重要工业基地,积极探索数字孪生技术在工业智能制造领域的应用,为制造业企业数字化…

ant-design-vue Notification 通知提醒框 内容换行

直接上代码 const msg errArr.map((message, index) > ${index 1}. ${message};) notification.open({message: ${statu.moduleName} 告警信息,description: () > {// 将msg所有;替换为\n换行符const res msg.replaceAll(;, \n)return h(pre,{style: {overflow: scro…

Transformer简单理解

目录 一、CNN存在的问题:二.Transformer整理架构分析:1.Linear Projection of Flattened Patches层形成Patch:2.对每个Patch进行位置编码Position Embedding:3.Transformer Encoder: 三.公式解读: 一、CNN存在的问题&a…

为什么使用 atan2(sin(z), cos(z)) 进行角度归一化?

文章目录 为什么使用 atan2(sin(z), cos(z)) 进行归一化?为什么归一化后的角度等于原始角度? atan2 方法返回 -π 到 π 之间的值,代表点 (x, y) 相对于正X轴的偏移角度。这个角度是逆时针测量的,以弧度为单位。关于 atan2 函数为…

【JAVA WEB】 Filter过滤器详解

目录 1,Filter 1.1 Filter概述 1.2 Filter快速入门 1.2.1 开发步骤 1.2.2 代码演示 1.3 Filter执行流程 1.4 Filter拦截路径配置 1.5 过滤器链 1.5.1 概述 1.5.2 代码演示 1.5.3 问题 1.6 案例 1.6.1 需求 1.6.2 分析 1.6.3 代码实现 1.6.3.1 创建Fi…

ERP系统怎么选 企业ERP管理系统选型建议

市面上有众多的ERP系统,而由于不同软件供应商的发展策略不同,导致不同ERP系统的侧重点也不同。例如有针对企业某一类管理需求的ERP系统,例如财务管理软件,进销存管理软件,仓库管理软件等。还有针对企业资源整合&#x…

element-ui表单验证同时用change与blur一起验证

项目场景: 提示:这里简述项目相关背景: 当审批时不通过审批意见要必须输入, 1:如果用change验证的话删除所有内容时报错是massage的提示,但是在失去焦点的时候报错就成了英文,如下图&#xf…