파일에서 패턴을 검색한 다음 패턴의 일부를 추출하거나 패턴이 없는 경우 기본값을 제공하는 방법은 무엇입니까?

파일에서 패턴을 검색한 다음 패턴의 일부를 추출하거나 패턴이 없는 경우 기본값을 제공하는 방법은 무엇입니까?

저는 다양한 컴퓨터에서 미리 만들어진 실행 중인 프로세스 목록을 검색하는 스크립트를 작성하려고 합니다. 나는 특히 이러한 장치에서 실행 중인 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(공백)(공백이 아닌 하나 이상의 문자)"가 포함되어 있는지 묻습니다. 그렇다면 정규식과 일치하는 하위 문자열을 4자만큼 오프셋하여 인쇄합니다(따라서 4만큼 단축됨). 문자) (공백) -f(공백) 을 설명합니다 . 그렇다면$s아니요기본 syslog.conf 경로를 인쇄하기 위한 위의 정규식을 포함합니다.

위의 코드는 기존 awk 스크립트의 끝에 배치되어 해당 print s섹션을 대체합니다(물론 재할당하지 않고 s=$0작업할 데이터가 있으므로 바로 거기에 있습니다).

관련 정보