如何在文件中搜索模式,然后提取部分模式或在模式不存在时提供默认值?

如何在文件中搜索模式,然后提取部分模式或在模式不存在时提供默认值?

我正在尝试编写一个脚本来搜索一系列机器上正在运行的进程的预制列表。我专门寻找在这些设备上运行的 rsyslogd,并尝试查找它们正在使用的配置文件(如果不使用默认的 /etc/rsyslog.conf)。

现在我正在使用这个 for 循环成功地搜索机器:

for root_file in $TARGET_DIR/RESULTS*/ps_results; do
    grep rsyslogd $root_file | awk '{s = ""; for (i = 15; i <= NF; i++) s = s $i " "; print s}'
done

它会返回一个类似的列表

# get_configs $TARGET_DIR/
/usr/sbin/rsyslogd -n
/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
/usr/sbin/rsyslogd -n -f /usr/syslog.conf
...

但我想要的是一个列表,其中显示正在检查的计算机的 IP 地址(按原样位于脚本的 RESULTS* 的 * 中),后跟配置文件的路径,如下所示:

# get_configs $TARGET_DIR/
172.16.10.1     /etc/syslog.conf
172.16.10.2     /etc/syslog.conf
172.17.5.245    /usr/syslog.conf
... 

我将获取此列表并解析文件并查找它们可能与指令链接的任何其他配置文件$IncludeConfig,但我必须首先清理我的文件列表。

我遇到的心理障碍是测试-frsyslogd 之后的选项。由于 rsyslogd 不需要-f并且它使用默认的 /etc/rsyslog.conf 运行,因此我如何处理该选项的测试并提取其后面的路径或提供默认值?

我考虑过使用sedorcut来隔离“-f /path/to/file”并在空结果上返回 /etc/rsyslog.conf,但我无法实现这一点。

答案1

假设我们有以下输入文件

$ grep . */ps_results
RESULTS-172.16.10.1/ps_results:/usr/sbin/rsyslogd -n
RESULTS-172.16.10.2/ps_results:/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
RESULTS-172.17.5.245/ps_results:/usr/sbin/rsyslogd -n -f /usr/syslog.conf
$

那么怎么样

$ awk '/rsyslogd/{gsub("^.*RESULTS-","",FILENAME);gsub("/ps_results","",FILENAME);b="/etc/rsyslog.conf";for(a=0;a++<NF;){if($a=="-f"){b=$(a+1)}};printf "%-15s%s\n",FILENAME,b}' RESULTS*/ps_results
172.16.10.1     /etc/rsyslog.conf
172.16.10.2     /etc/rsyslog.conf
172.17.5.245    /usr/syslog.conf
$

相同的代码,注释+格式化:

awk '/rsyslogd/ {
   # strip everything up to (and including) RESULTS- from the filename
   gsub("^.*RESULTS-","",FILENAME)
   # strip the /ps_results from the filename
   gsub("/ps_results","",FILENAME)
   # set the default rsyslog conf file
   b="/etc/rsyslog.conf"
   # look for a -f parameter: if found, grab conf file
   for(a=0;a++<NF;){
     if($a=="-f") {
       b=$(a+1)
     }
   }
   # print the ip addr and conf file
   printf "%-15s%s\n",FILENAME,b
}' RESULTS*/ps_results

答案2

您可以像这样扩展现有的 awk (这是一个人为的独立示例):

awk '{ s=$0; 
       if (match($s, / -f [^ ]+/)) { 
         print substr($s, RSTART+4, RLENGTH-4) 
       } 
       else 
          print "/etc/syslog.conf" 
     }' < input

这询问字符串是否$s包含正则表达式“(space) -f (space)(一个或多个非空格字符)”;如果是这样,则打印与正则表达式匹配的子字符串,偏移 4 个字符(并相应地缩短 4 个字符),以考虑 (space) -f(space)。如果$s是的话不是包含上面的正则表达式,打印默认的syslog.conf路径。

上面的代码将放在现有 awk 脚本的末尾,替换该print s部分(当然,不会重新分配s=$0——那只是在那里,所以我有数据可以使用)。

相关内容