sed를 사용하여 캡처 그룹 콘텐츠를 교체하기 위한 RegEx

sed를 사용하여 캡처 그룹 콘텐츠를 교체하기 위한 RegEx
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\nperl

$ 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줄을 합칠 때까지 일치하지 않습니다(당신이 하지 않는 일)

이제 나는 당신이 무엇을 하려고 했는지 감히 추측해 봅니다. messagesand securelog의 경우 다음 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이 제안한 패턴을 더욱 단순화)

관련 정보