ファイルからパターンを検索し、パターンの一部を抽出するか、パターンがない場合のデフォルト値を提供する方法は?

ファイルからパターンを検索し、パターンの一部を抽出するか、パターンがない場合のデフォルト値を提供する方法は?

私は、さまざまなコンピュータで事前に作成された実行中のプロセスのリストを取得するスクリプトを作成しようとしています。私は特に、これらのデバイスで実行されている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として実行されるので、そのオプションのテストをどのように処理し、その背後にあるパスを抽出したりデフォルト値を提供したりできますか?

sedORを使用して "-f /path/to/file"を分離し、空の結果に/etc/rsyslog.confを返そうとしましたが、cutこれを達成できませんでした。

答え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に正規表現「(空白)-f(空白)(空白ではなく1つ以上の文字)」が含まれているかどうかを尋ねます。その場合は、正規表現に一致する部分文字列を4文字ずつオフセットして印刷します(したがって4だけ短縮されます)。文字)(スペース)-f(スペース)について説明します。$sもしそうならいいえデフォルトのsyslog.confパスを印刷するための上記の正規表現が含まれています。

上記のコードは既存のawkスクリプトの末尾に配置され、そのprint sセクションを置き換えます(もちろん、再割り当てせずにs=$0作業するデータがあるのですぐそこにあります)。

関連情報