RegEx zum Ersetzen von Capture-Gruppeninhalten mithilfe von sed

RegEx zum Ersetzen von Capture-Gruppeninhalten mithilfe von 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 

Antwort1

Dies wäre in Perl viel einfacher zu bewerkstelligen. Die perlausführbare Datei verfügt über einen sogenannten „Absatzmodus“ ( -00), in dem eine „Zeile“ durch zwei aufeinanderfolgende \nZeichen (also eine leere Zeile) definiert wird. Dies ermöglicht perldas Arbeiten mit Absätzen statt mit Zeilen. Sie könnten also einfach Folgendes tun:

$ 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

Und:

$ 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=

Da Ihre Dateien jedoch ein ziemlich stabiles Format zu haben scheinen, könnten Sie es folgendermaßen weiter vereinfachen:

$ 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

Und:

$ 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=

Antwort2

1) Bei einem Muster mit vielen Schrägstrichen sollten Sie ein anderes Trennzeichen für den Befehl verwenden, sum ihn lesbarer zu machen (Sie müssen die Schrägstriche dann nicht maskieren).

2) Sie scheinen erweiterte reguläre Ausdrücke zu verwenden, daher müssen Sie die -EOption aufsed

3) Wenn Sie alternative Zeichenfolgen für einen Teil des Musters verwenden, müssen Sie diese mit ()Folgendem umgeben:(messages|secure)

4) Der Ersetzungsteil ( /index=window) muss Teil des Skripts sein und darf nicht wie ein Argument abgetrennt werden.

5) Außerdem sfehlt dem Befehl ein schließendes Trennzeichen

6) (?s) and(?:)` sind keine regulären Ausdrücke, sondern Perl-Erweiterungen, also verwenden Sie sie hier nicht. Und da der Doppelpunkt hier keine besondere Bedeutung hat, müssen Sie ihn nicht maskieren (danke, @Stéphane Chazelas)

7) sedarbeitet zeilenweise, sodass es \nnie zu einer Übereinstimmung kommt, bis Sie die Zeilen verbinden (was Sie nicht tun)

Jetzt wage ich zu raten, was Sie versucht haben: Ändern Sie für das messagesund securedas Protokoll die folgende index=Zeile in index=secure. Richtig?

Ihr Befehl lautet also s/index=/index=secure/. Sie möchten ihn aber nur auf bestimmte Gruppen anwenden. Zu diesem Zweck sedgibt es eine Filteroption, um Befehle nur auf Zeilen (oder Zeilengruppen) anzuwenden, die dem Filter entsprechen. Eine Möglichkeit, Zeilen nach einem abzugleichenden Muster zu adressieren, besteht darin, zwei Adressen (Start- und Endadresse) anzugeben, die durch ein Komma getrennt sind:

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

Beim zweiten Befehl kann ich zeigen, wie man den Befehl noch weiter vereinfachen kann: Man kann das passende Muster im sBefehl weglassen. Das bedeutet, dass das letzte Muster erneut verwendet wird, das zufällig die zweite Adresse des Filterbereichs ist, sodass es nicht wiederholt werden muss.

Und anstatt das Muster beim Ersetzen zu wiederholen, können Sie schreiben &, wodurch die gesamte Übereinstimmung eingefügt wird:

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

Ein letzter Hinweis: Verwenden Sie die -iOption erst, wenn Sie mit dem Ergebnis zufrieden sind. Sie können Ihre Datei auf diese Weise leicht durcheinander bringen, insbesondere wenn Sie mit dem Tool unerfahren sind.

Aktualisieren

Bei der aktualisierten Frage scheint es möglich, dass bereits eine index=fooEinstellung vorhanden ist, die ersetzt werden muss. Ändern Sie einfach den Ersatz:

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

Und

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

(weitere Vereinfachung des von Terdon vorgeschlagenen Musters)

verwandte Informationen