【发布时间】:2019-02-06 19:41:26
【问题描述】:
请帮助我了解更高级的 sed 语法。按照我的理解,我可以在一个字符串中使用两个 sed 命令来搜索模式,然后有条件地插入该模式之后。这是目标。我有一个这样的文件:
[PATTERN]
String
只有当“String”不存在时,我才需要 sed 在 [PATTERN] 之后插入“String”。
"String" 使用 Ansible 变量,基本上是这样的:
{{ hostname.droplet.name }} ansible_ssh_host={{ hostname.droplet.ip_address }}
这翻译成
hostname ansible_ssh_host=X.X.X.X
所以最终我将有以下现实世界(非概念性)示例:
[DROPLETS]
ilovetacos ansible_ssh_host=127.0.0.1
如果 [DROPLETS] 下面没有匹配的行,则追加该行。如果特定的主机名行已经存在,则不要再次添加该行。
我可以处理第一部分:
sed '/\[DROPLETS\]/a STRING' inventory
现在这是我的第一个问题。我不知道如何处理 sed 命令中的 ansible 变量?也许是这样?
sed '/\[DROPLETS\]/a "{{ hostname.droplet.name }} ansible_ssh_host={{ hostname.droplet.ip_address }}"' inventory
下一部分是添加条件检查。我曾考虑过先 greping 这条线,然后再通过管道传输到 sed,但似乎有更好的方法可以使用单个 sed 命令完成所有这些操作。有人可以帮助我使用这种更高级的语法吗?
谢谢
【问题讨论】:
-
为什么不用 Ansible 的
lineinfile模块调用替换sed? -
是的,我完全同意,但具有讽刺意味的是,我尝试这种方式的全部原因是我们在 lineinfile 模块中发现了一个错误。那是另一种蠕虫,但基本上,尽管验证了变量的内容,lineinfile 模块仍无法将所有输出写入文件。我们测试了一切。想也许文件被锁定了。认为变量可能不完整,等等。我们最终不得不放弃模块并选择纯 shell 选项。我根本不喜欢这样做......感觉不对,并且反对 Ansible 的一切,但到目前为止我们别无选择。
-
正确的建议!
-
因此,根据您的示例,您似乎正在动态构建库存文件。这表明
[DROPLETS]下可能有任意数量的主机,所以您不一定只是在下面直接寻找匹配项?可靠地解决这将是相当棘手的。在深入探讨之前,您是否考虑过编写动态库存脚本? (docs.ansible.com/ansible/latest/dev_guide/…) -
完全同意@clockworknet 但如果由于某种原因这不是你的情况,那么我的后续建议是使用实际的脚本语言,因为 sed 真的不是为了做很多“有状态的” “ 事物。你也可以使用
awk,它有更丰富的变量,如果你真的坚决反对使用脚本语言...