sed를 사용하여 캡처 그룹 내용을 바꾸는 정규식

sed를 사용하여 캡처 그룹 내용을 바꾸는 정규식
Have inputs.conf files in multiple directories that needs to match and parse each stanza and modify the index= to index=secure. This are files type in inputs.conf and also do run the script to locate the inputs file in this dir (_GWAS_pr_linux_t1/local/inputs.conf) to modify the index

In the file

    [WinEventLog://Application]
    checkpointInterval = 5
    current_only = 0
    disabled =0 
    start_from = oldest
    index = 

    [WinEventLog://Security]
    checkpointInterval = 5
    current_only = 0
    disabled =0 
    start_from = oldest
    index = 

    [WinEventLog://System]
    checkpointInterval = 5
    current_only = 0
    disabled =0 
    start_from = oldest
    index = 

    [WinEventLog://ForwardedEvents]
    checkpointInterval = 5
    current_only = 0
    disabled =0 
    start_from = oldest
    index = 

    [WinEventLog://Setup]
    checkpointInterval = 5
    current_only = 0
    disabled =0 
    start_from = oldest
    index = 

I tried with the command

    sed -i -e 's/.*(?s)((\[WinEventLog:\/\/Application|Security|System|ForwardedEvents|Setup\]).*?)(?:(?:\r\n){2}) /index=window inputs.conf

to change to `index=window` for the `Application`, `Security`, `System`, `ForwardedEvents` and `Setup` entry.

In the file

    [monitor:///var/log/cron]
    index=
    sourcetype=linux_secure

    [monitor:///var/log/secure]
    index=
    sourcetype=linux_secure

    [monitor:///var/log/messages]
    index=
    sourcetype=linux

    [monitor:///var/log/spooler]
    index = 
    sourcetype=syslog

    [monitor:///var/log/audit/audit.log]
    sourcetype=syslog
    index=

    [monitor:///var/log//maillog]
    index=
    sourcetype=syslog

I tried command

    sed -i -e 's/.*(?s)((\[monitor\:\/\/\/var\/log\/messages|secure\]).*?)(?:(?:\r*\n){2})' /index=secure *linux*/local/inputs.conf

to change the `index=` line to `index=secure` for the `messages` and `secure` log.


i) Work like a charm but the only issues I'm having right now is that, the 
 script cannot pass through the apps directory and update the index name and 
 most of the apps directory name is in this form.

     _EBPD_pr_linux_w1/local/inputs.conf,
     _EBPD_np_linux_w1/local/inputs.conf,
     _FBPV_pr_liux_e1/local/inputs.conf, 
    _FBPV_np_liux_e1/local/inputs.conf,
     _FBPV_np_windows_e1/local/inputs.conf,
     _FBPV_np_windows_e1/ocal/inputs.conf


ii) Secondly, the most important thing is that, if the app has `np` or `pr` that is how the index name will be updated. For example `index=secure_pr` or `scure_np` or `windows_pr` or `windows_np`.


iii) Another issue is that if there is an existing index name, it does not remove and update to the new index name it just adds to it. For example `index=power` is updated to `index=powersecure` instead of `index=secure`.


iv) I try these but it says "No such file or directory"

    perl -00lpe '$_.="secure_np" if m,/(messages|secure|cron|maillog|spooler|audit/audit\.log)\],' *linux*/local/inputs.conf 

    perl -00lpe '$_.="secure_pr" if m,/(messages|secure|cron|maillog|spooler|audit/audit\.log)],' *linux*/local/inputs.conf 

    perl -00lpe '$_ .= "windows_pr" if m,/(Application|Security|System|ForwardedEvents|Setup)\],' *window*/local/inputs.conf 

    perl -00lpe '$_ .= "windows_nr" if m,/(Application|Security|System|ForwardedEvents|Setup)],' *window*/local/inputs.conf 

답변1

Perl에서는 이것이 훨씬 더 쉽습니다. 실행 파일에는 perl"단락 모드"( )라는 기능이 있습니다. 여기서 "줄"은 -00두 개의 연속 문자(예: 빈 줄)로 정의됩니다. 이렇게 하면 줄 대신 단락을 사용할 \n수 있습니다 . perl따라서 간단하게 다음과 같이 할 수 있습니다.

$ perl -00pe 'if(m,^\[WinEventLog://(Application|Security|System|ForwardedEvents|Setup)\],){s/(index\s*=)\s*[^\n]*/$1 window inputs.conf\n\n/}' file1
[WinEventLog://Application]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://Security]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://System]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://ForwardedEvents]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://Setup]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

그리고:

$ perl -00pe 'if(m,^\[monitor:///var/log/(messages|secure)\],){s/(index\s*=)\s*[^\n]*/$1 secure\n\n/}' file2
[monitor:///var/log/cron]
sourcetype=linux_secure
index=

[monitor:///var/log/secure]
sourcetype=linux_secure
index= secure

[monitor:///var/log/messages]
sourcetype=linux
index= secure

[monitor:///var/log/spooler]
sourcetype=syslog
index = 

[monitor:///var/log/audit/audit.log]
sourcetype=syslog
index=

[monitor:///var/log//maillog]
sourcetype=syslog
index=

그러나 파일 형식이 상당히 안정적인 것으로 보이므로 다음과 같이 더 단순화할 수 있습니다.

$ perl -00lpe '$_ .= "window inputs.conf" if m,//(Application|Security|System|ForwardedEvents|Setup)\],;' file1
[WinEventLog://Application]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://Security]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://System]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://ForwardedEvents]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

[WinEventLog://Setup]
checkpointInterval = 5
current_only = 0
disabled =0 
start_from = oldest
index = window inputs.conf

그리고:

$ perl -00lpe '$_.="secure" if m,/(messages|secure)\],' file2
[monitor:///var/log/cron]
sourcetype=linux_secure
index=

[monitor:///var/log/secure]
sourcetype=linux_secure
index=secure

[monitor:///var/log/messages]
sourcetype=linux
index=secure

[monitor:///var/log/spooler]
sourcetype=syslog
index = 

[monitor:///var/log/audit/audit.log]
sourcetype=syslog
index=

[monitor:///var/log//maillog]
sourcetype=syslog
index=

답변2

1) 슬래시가 많은 패턴의 경우 명령을 s더 쉽게 읽을 수 있도록 다른 구분 기호를 사용해야 합니다(그러면 슬래시를 이스케이프할 필요가 없습니다).

2) 확장 정규식을 사용하고 있는 것으로 보이므로 -E옵션을 다음으로 설정 해야 합니다.sed

3) 패턴의 일부에 대체 문자열을 사용하는 경우 ()다음과 같은 문자열로 묶어야 합니다.(messages|secure)

4) 교체부분( /index=window)은 매개변수처럼 분리되지 않고 스크립트의 일부로 포함되어야 합니다.

5) 또한 s명령에 닫는 구분 기호가 없습니다.

6) (?s) and(?:)`는 정규 표현식이 아니고 Perl 확장이므로 여기서는 사용하지 마세요. 여기서 콜론은 특별한 의미가 없으므로 이스케이프 처리할 필요가 없습니다. (감사합니다, @Stéphane Chazelas)

7) sed행 단위로 작업하므로 \n행을 조인할 때까지 일치하지 않습니다.

이제 당신이 무엇을 하고 싶은지 추측해 보겠습니다. for 및 messageslog 에서 secure다음 줄을 index=로 변경합니다 index=secure. 옳은?

따라서 귀하의 명령은 입니다 s/index=/index=secure/. 그러나 특정 그룹에만 적용하려고 합니다. 이를 위해 sed필터와 일치하는 행(또는 행 그룹)에만 명령을 적용하는 필터 옵션이 있습니다. 일치시킬 패턴을 지정하는 방법입니다. 여러 줄의 주소를 지정하려면 쉼표로 구분된 두 개의 주소(시작 및 끝)를 제공하세요.

sed -E '\_\[WinEventLog://(Application|Security|System|ForwardedEvents|Setup)\]_,/index *=/s/index =/index = window/' inputs.conf

두 번째 명령에서는 명령을 더욱 단순화하는 방법을 보여줄 수 있습니다. s명령에서 일치하는 패턴을 제거할 수 있습니다. 이는 필터 범위의 두 번째 주소인 마지막 패턴을 다시 사용한다는 의미이므로 반복할 필요가 없습니다.

교체 시 패턴을 반복하는 대신 다음과 같이 작성할 수 있습니다. &그러면 전체 일치 항목이 삽입됩니다.

sed -i -E '\_\[monitor:///var/log/(messages|secure)\]_,/index=/s//&secure/' *linux*/local/inputs.conf

-i최종 팁: 결과에 만족할 때까지 이 옵션을 사용하지 마십시오. 이렇게 하면 특히 도구 사용 경험이 없는 경우 파일을 쉽게 엉망으로 만들 수 있습니다.

고쳐 쓰다

index=foo업데이트된 질문을 보면 이미 교체해야 할 일부 설정이 있는 것 같습니다 . 대체 항목을 변경하십시오.

sed -E '/(Application|Security|System|ForwardedEvents|Setup)]/,/index *=.*/s//index = window/' inputs.conf

그리고

sed -i -E '/messages]|secure]/,/index *=.*/s//index=secure/' *linux*/local/inputs.conf

(terdon이 제안한 패턴을 더욱 단순화)

관련 정보