尽可能简单地说,在使用 bash/sed/awk 和基本操作系统命令的 Linux 中,我尝试在文本文件中创建一个包含多个标题的列表,其中下面有一堆字符串(服务器名称)。然后,我希望能够有一个脚本,并对我在运行时作为选项/参数传递的特定标题下的每个条目运行各种任务。
此文本文件的示例:(这些条目应在单列中的相关标题下排序,我只是无法让它在此页面上以这种方式显示。)
[main_server_list]
Jupiter
Saturn
Thisguy
Thatguy
BuffalO
randomspite
coffeebinge
[alternate_server_list]
Jupiter
Saturn
[Tertiary_server_list]
Thisguy
Thatguy
coffeebinge
[Enough_already]
BuffalO
randomspite
所以基本上,如果我想将文件复制到我所有机器的目录中,我会想做类似的事情:
# bash maincopyscript.sh [main_server_list]
并且“循环”会知道要安装它的服务器列表将是 [main_server_list] 标头下的每个条目,但忽略任何其他标头下的其他所有内容。
同样,我也希望能够做到:
# bash maincopyscript.sh [Tertiary_server_list]
并期望相同的功能,只是这一次,仅在 [Tertiary_server_list] 标头下的条目上运行“循环”,然后完成。
最后,如果我愿意的话,我希望能够指定多个标头,以任何顺序指定。例如:
# bash maincopyscript.sh [Enough_already] [alternate_server_list]
然后,它应该仅对这两个标头下的条目运行脚本中指定的操作,然后完成。
希望您明白了,基本上是一种主要利用 bash/sed/awk 来完成此操作的方法。 (如果需要的话甚至可以使用其他工具)
是的,我知道 ansible/puppet/chef 也可以帮助我实现这些结果,但无论如何我都有特定的理由想要这样做。我尝试花一两个小时搜索任何有关此问题的现有帖子,但找不到,所以最后决定提出我的问题。任何帮助,将不胜感激!
(奖励,如果有人还可以向我展示如何按字母顺序将条目放在每个标题下,同时保持标题和组本身处于完全相同的格式,那就太棒了!)
答案1
您可以使用 awk 从标题下提取名称,然后将它们扔进大批 多变的,然后使用 迭代数组for
。这里的脚本从命令行获取模式。
#!/bin/bash
patt=$1
if [ -z "$patt" ] ; then echo "need an argument" ; exit 1 ; fi
A=( $(awk '/^\[/ {p = 0};
/^\['"$patt"'\]/ {p=1; next}
p && !/^ *$/ ;' < servers ) )
for x in "${A[@]}" ; do
echo doing something with "$x"
done
所以,
$ bash for_all.sh alternate_server_list
doing something with Jupiter
doing something with Saturn
在awk
程序中:
/^\[/ {p = 0}
- 如果开括号是该行的第一个字符,则将 p 设置为零,
/^\['"$patt"'\]/ {p=1; next}
- 如果我们匹配模式,则将 p 设置为 1 并跳到下一行。请注意,模式是从 shell 变量赋予 awk 的,因此它将被视为正则表达式。引号有点有趣,因为单引号中有部分代码,双引号中有变量,然后单引号中有更多代码。喜欢'foo' "$var" 'bar'
但没有空格。
p && !/^ *$/
- 如果设置了 p 并且该行不为空(开始和结束之间只有空格),则打印它(默认操作)。
哦,而且,如果您的列表项包含任何有趣的内容(例如空格),这将会崩溃并烧毁。