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

时间:2022-09-13 12:47:00

I'm trying to write a script that searches through a pre-made list of running processes across a series of machines. I'm specifically looking for rsyslogd running on those devices, and attempting to find what configuration file they're using (if not using the default /etc/rsyslog.conf).

我正在尝试编写一个脚本,在一系列机器上搜索预先制定的正在运行的进程列表。我特意在寻找在这些设备上运行的rsyslogd,并试图找到他们正在使用的配置文件(如果没有使用默认的/etc/rsyslog.conf)。

Right now I'm successfully searching through the machines with this for loop:

现在我用这个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

And it'll return a list like

它会返回一个列表

# 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
...

But what I want is a list that shows the IP address of the machine that is being checked (which is in the * of the RESULTS* of the script as-is) followed by just the path to the configuration file, like so:

但我想要的是一个列表,显示正在检查的机器的IP地址(在脚本的结果*的*中),后面只是配置文件的路径,如下所示:

# 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
... 

I'll be taking this list and parsing through the files and finding any additional configuration files that they might link to with the $IncludeConfig directive, but I've got to get through cleaning up my list of files first.

我将使用这个列表并解析文件并找到他们可能使用$ IncludeConfig指令链接到的任何其他配置文件,但我必须首先清理我的文件列表。

The mental block I'm hitting is testing for the -f option following rsyslogd. Since rsyslogd doesn't require -f and it runs with the default /etc/rsyslog.conf, how do I handle testing for the option and extracting the path following it or supplying a default?

我正在尝试的心理块正在测试rsyslogd之后的-f选项。由于rsyslogd不需要-f并且它使用默认的/etc/rsyslog.conf运行,如何处理该选项的测试并提取其后的路径或提供默认值?

I considered using sed or cut to isolate ' -f /path/to/file' and return /etc/rsyslog.conf on an empty result, but I'm not managing to accomplish that.

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

2 个解决方案

#1


2  

Supposing we have the following input files

假设我们有以下输入文件

$ 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
$

Then how about

那怎么样

$ 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
$

Same code, annotated+formatted:

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

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


1  

You could extend your existing awk like this (this is a contrived self-contained example):

你可以像这样扩展你现有的awk(这是一个人为的自成一体的例子):

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

This asks if the string $s contains the regular expression "(space) -f (space) (one or more non-space characters)"; if so, then print the substring that matched the regular expression, offset over by 4 characters (and correspondingly shortened by 4 characters), to account for the (space) -f (space). If $s does not contain the above regular expression, print the default syslog.conf path.

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

The above code would go at the end of your existing awk script, replacing the print s portion (and, of course, not reassigning s=$0 -- that's just there so I had data to work with).

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

#1


2  

Supposing we have the following input files

假设我们有以下输入文件

$ 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
$

Then how about

那怎么样

$ 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
$

Same code, annotated+formatted:

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

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


1  

You could extend your existing awk like this (this is a contrived self-contained example):

你可以像这样扩展你现有的awk(这是一个人为的自成一体的例子):

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

This asks if the string $s contains the regular expression "(space) -f (space) (one or more non-space characters)"; if so, then print the substring that matched the regular expression, offset over by 4 characters (and correspondingly shortened by 4 characters), to account for the (space) -f (space). If $s does not contain the above regular expression, print the default syslog.conf path.

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

The above code would go at the end of your existing awk script, replacing the print s portion (and, of course, not reassigning s=$0 -- that's just there so I had data to work with).

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