RegEx для замены содержимого группы захвата с помощью sed

RegEx для замены содержимого группы захвата с помощью 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никогда не сравняетесь, пока не объедините строки (чего вы не делаете)

Теперь я осмелюсь предположить, что вы пытались сделать: для журнала messagesи 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)

Связанный контент