Próbuję programowo edytować mój plik nginx.conf, który zawiera taką linię:
access_log /var/log/nginx/access.log;
które chcę wyglądać tak:
access_log /dev/stdout;
Wierzę, że regex ^\s*access_log([^;]*);
uchwyci /var/log/nginx/access.log
część w grupie przechwytywania, ale nie jestem pewien, jak poprawnie zastąpić grupę przechwytywania przez sed?
próbowałem
echo " access_log /var/log/nginx/access.log;" | sed 's/^\s*access_log([^;]*);/\1\\\/dev\\\/stdout/'
ale pojawia się błąd:
sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS
jeśli spróbuję, sed -r
nie będzie żadnego błędu, ale wynik nie jest zgodny z oczekiwaniami:
/var/log/nginx/access.log\/dev\/stdout
Staram się być mądry z grupą przechwytywania i tym podobne, a nie szukać bezpośrednio „access_log /var/log/nginx/access.log;” w przypadku gdy dystrybucja zmieni domyślną lokalizację pliku dziennika.
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Odpowiedzi:
Kilka błędów.
Po pierwsze, ponieważ
sed
używa podstawowych wyrażeń regularnych, musisz\(
i\)
utworzyć grupę przechwytywania.-r
Przełącznik umożliwia rozszerzone wyrażenia regularne, dlatego nie pojawia się błąd. Zobacz Dlaczego muszę uciec znakom regularnym w sed, aby interpretować je jako znaki regularne? .Po drugie, umieszczasz grupę przechwytywania w niewłaściwym miejscu. Jeśli dobrze cię rozumiem, możesz to zrobić:
Zwróć uwagę na użycie
!
jako ograniczników wyrażeń regularnych, aby uniknąć konieczności ucieczki przed ukośnikami/dev/stdout
.źródło
W swoim wyrażeniu regularnym powinieneś wiedzieć, że
\No.
jest to odniesienie do wzorca w nawiasach()
. Tak więc wyrażenie regularne powinno być's@^(\s*access_log ).*$@\1/dev/stdout/;@'
mogę zaoferować
WSKAZÓWKA: Niezależnie od tego, czy zamierzasz używać
/
wewnątrz patern, możesz dowolnie zmieniaćs///
każdy symbol,s###
na przykładźródło
Zamiast go schwytać, dlaczego nie po prostu go znaleźć i dokonać zamiany? To znaczy:
Wyszukuje wiersze pasujące do „
access_log
”, a następnie wszystkie wiersze, które to zrobią, zastąpią „/whatever/path/is/there;
” „/dev/stdout;
”źródło