如何使用sed替换多行字符串?

eri*_*ric 5 sed

如何使用bash sed命令更改此字符串:

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
Run Code Online (Sandbox Code Playgroud)

进入以下字符串?(仅更改第3行字符串)

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
Run Code Online (Sandbox Code Playgroud)

注1:我不只是想要将字符串'AllowOverride None'作为目标,因为文件中还有其他一些不应该更改的事件.我需要以#开头的整个字符串为目标<Directory /var/www>

注2:我还需要覆盖该文件.所以,在你的答案中考虑到这一点.并提供不同版本的GNU /非GNU版本的sed以防万一.

Jon*_*ler 7

由于模式包含斜杠,因此请使用\%(对于任何字符%)标记搜索模式.然后使用:

sed -e '\%^<Directory /var/www/>%,\%^</Directory>% s/AllowOverride None/AllowOverride All/'
Run Code Online (Sandbox Code Playgroud)

内部的搜索模式将搜索\%…%限制为匹配模式之间的线条,并{ s/…/…/; }在该范围内查找所需模式并进行适当的替换.

如果您不想将其限制为单个目录部分而是限制所有目录部分,请相应地调整启动模式.例如,这将匹配任何<Directory>部分:

sed -e '\%^<Directory [^>]*>%,\%^</Directory>% s/AllowOverride None/AllowOverride All/'
Run Code Online (Sandbox Code Playgroud)

您可以根据自己的要求使其更具选择性.

  • 使用`sed -i.bak -e'...'file.txt`.使用`> file.txt`覆盖输入文件是一种创建空文件(或删除以前非空文件)的昂贵方法. (2认同)

小智 1

我意识到这不是你问的也许不值得使用 sed?

python 解决方案怎么样?它遍历作为第一个参数传递给脚本的目录,并准确 <Directory替换您编写的元素,同时更改NoneAll文件并将更改写回文件。它还可以使用不同的缩进级别,同时保留原始缩进。适用于 python2 和 python3。

毕竟我假设如果你有 sed 你可能也有 python。

#!/usr/bin/env python
import re

r = re.compile(r'(<Directory /var/www/>\s+Options Indexes FollowSymLinks\s+AllowOverride )None(\s+Require all granted\s+</Directory>)', re.MULTILINE)

for root, dirs, files in os.walk(sys.argv[1]):
    for file_name in files:
        if file_name.endswith('.conf'):
            file_path = os.path.join(root, file_name)
            with open(file_path) as fp:
                data = r.sub(r'\1All\2', fp.read())
            with open(file_path, 'w+') as fp:
                fp.write(data)
Run Code Online (Sandbox Code Playgroud)