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


16

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

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

我想看起来像这样:

        access_log /dev/stdout;

我相信正则表达式^\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/'

但我得到了错误:

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

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

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

我试图对捕获组和其他方面变得聪明,而不是直接搜索“ access_log /var/log/nginx/access.log;”。如果发行版更改了默认日志文件位置。


1
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Costas 2014年

@Costas如果您能回答这个问题,我会投票给您,因为它也可以!
安倍·沃克

Answers:


16

那里有两个错误。

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

其次,您将捕获组放在错误的位置。如果我对您的理解正确,则可以执行以下操作:

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

请注意,使用!as作为正则表达式定界符可以避免必须转义正斜杠/dev/stdout


谢谢,工作出色!我目前无法将其标记为已接受,但会在9分钟后返回。
2014年

1
@AbeVoelker非常欢迎。很高兴能为您提供帮助。
Joseph R.

5

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

我可以提供

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

提示:无论你打算使用/您可以自由改变百通里面s///的每一个你想要的符号s###,例如


谢谢,我希望我能接受两个答案!在看到解决方案后寻求帮助之前,我不再后悔没有完全阅读手册页。
2014年

3

而不是捕获它,为什么不找到它并进行替换呢?即:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.