使用 sed 替换正则表达式捕获组内容

Abe*_*ker 29 sed

我正在尝试以编程方式编辑我的 nginx.conf 文件,其中包含如下一行:

        access_log /var/log/nginx/access.log;
Run Code Online (Sandbox Code Playgroud)

我想看起来像这样:

        access_log /dev/stdout;
Run Code Online (Sandbox Code Playgroud)

我相信正则表达式^\s*access_log([^;]*);会捕获/var/log/nginx/access.log捕获组中的部分,但我不确定如何用 sed 正确替换捕获组?

我试过了

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

但我收到错误:

sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS
Run Code Online (Sandbox Code Playgroud)

如果我尝试sed -r,则没有错误,但输出不是我所期望的:

 /var/log/nginx/access.log\/dev\/stdout
Run Code Online (Sandbox Code Playgroud)

我试图对捕获组和诸如此类的东西保持聪明,而不是直接搜索“access_log /var/log/nginx/access.log;” 以防分发更改默认日志文件位置。

Jos*_* R. 35

那里有几个错误。

首先,由于sed使用基本的正则表达式,你需要\(\)做一个捕获组。该-r开关启用扩展的正则表达式,这就是您不会收到错误消息的原因。请参阅为什么我需要将 sed 中的正则表达式字符转义为正则表达式字符?.

其次,您将捕获组放在错误的位置。如果我理解正确,你可以这样做:

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

请注意使用!as 正则表达式分隔符以避免转义/dev/stdout.


Cos*_*tas 7

在您的正则表达式中,您应该知道这\No.是对括号内模式的反向引用()。所以正则表达式应该是's@^(\s*access_log ).*$@\1/dev/stdout/;@'

我可以提供

sed '/access_log/s|/[^;]\+|/dev/stdout|'
Run Code Online (Sandbox Code Playgroud)

提示:无论您打算在模式内使用/,您都可以自由更改s///您想要的每个符号s###,例如


Jer*_*vis 5

与其捕获它,为什么不直接找到它并进行替换呢?IE:

sed "/access_log/ s| /.*;| /dev/stdout;|"
Run Code Online (Sandbox Code Playgroud)

它搜索匹配“ access_log”的行,然后在任何匹配的行上将“ /whatever/path/is/there;”替换为“ /dev/stdout;