Ersetzen Sie den Inhalt der Regex-Erfassungsgruppe durch sed

16

Ich versuche, meine Datei nginx.conf programmgesteuert zu bearbeiten, die eine Zeile wie die folgende enthält:

        access_log /var/log/nginx/access.log;

was ich so sehen will:

        access_log /dev/stdout;

Ich glaube, der Regex ^\s*access_log([^;]*);erfasst den /var/log/nginx/access.logTeil in einer Erfassungsgruppe, aber ich bin nicht sicher, wie ich die Erfassungsgruppe richtig durch sed ersetzen soll.

ich habe es versucht

echo "        access_log /var/log/nginx/access.log;" | sed 's/^\s*access_log([^;]*);/\1\\\/dev\\\/stdout/'

aber ich erhalte den Fehler:

sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS

wenn ich es versuche sed -rdann liegt kein fehler vor, aber die ausgabe ist nicht das was ich erwarte:

 /var/log/nginx/access.log\/dev\/stdout

Ich versuche, mit der Erfassungsgruppe und so weiter schlau zu sein und nicht direkt nach "access_log /var/log/nginx/access.log;" zu suchen. Falls die Verteilung den Standardspeicherort der Protokolldatei ändert.

Abe Voelker
quelle
1
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Costas
@Costas Wenn du das beantworten würdest, würde ich dich unterstützen, da das auch funktioniert!
Abe Voelker

Antworten:

16

Ein paar Fehler da.

Erstens, da sedAnwendungen grundlegende reguläre Ausdrücke, müssen Sie \(und \)eine Capture - Gruppe zu machen. Der -rSchalter aktiviert erweiterte reguläre Ausdrücke, weshalb der Fehler nicht angezeigt wird. Siehe Warum muss ich Regex-Zeichen in sed maskieren, um als Regex-Zeichen interpretiert zu werden? .

Zweitens platzieren Sie die Erfassungsgruppe am falschen Ort. Wenn ich Sie richtig verstehe, können Sie dies tun:

sed -e 's!^\(\s*access_log\)[^;]*;!\1 /dev/stdout;!' your_file

Beachten Sie die Verwendung von !Regex-Trennzeichen, um die Schrägstriche nicht zu umgehen /dev/stdout.

Joseph R.
quelle
Danke, funktioniert wunderbar! Ich kann dies noch nicht als akzeptiert markieren, werde aber in 9 Minuten zurück sein, um dies zu tun.
Abe Voelker
1
@ BeVoelker Gern geschehen. Es freut mich, dass ich helfen konnte.
Joseph R.
5

In Ihrem regulären Ausdruck sollten Sie wissen, dass dies \No.der Rückverweis auf Muster in Klammern ist (). So sollte regexp sein's@^(\s*access_log ).*$@\1/dev/stdout/;@'

ich kann anbieten

sed '/access_log/s|/[^;]\+|/dev/stdout|'

TIPP: Unabhängig davon, ob Sie das Muster /innerhalb des Musters verwenden möchten, können Sie es s///für jedes Symbol ändern, das Sie s###beispielsweise möchten

Costas
quelle
Danke, ich wünschte, ich könnte zwei Antworten akzeptieren! Ich bedaure nicht mehr, die Manpages nicht vollständig gelesen zu haben, bevor ich nach den Lösungen um Hilfe gebeten habe.
Abe Voelker
3

Warum nicht einfach finden und ersetzen, anstatt es einzufangen? Dh:

sed "/access_log/ s| /.*;| /dev/stdout;|"

Es sucht nach Zeilen, die " access_log" übereinstimmen, und ersetzt " " in allen Zeilen, die dies tun, durch /whatever/path/is/there;" /dev/stdout;".

Jeremy Davis
quelle