替换其他正则表达式结果的结果

时间:2016-09-21 11:01:44

标签: regex bash replace

我正在尝试为CentOS服务器自动化一些东西。对于这种自动化,我需要添加,替换或修改文件行。这可以通过全局替换或替换唯一行来正常工作。

sed -i "s/user \\= apache/user \\= nginx/" file.conf

这会将user = apache替换为user = nginx,但效果正常。

但有时我需要在其他正则表达式的结果中替换这些行。例如,文件/etc/php-fpm.d/www.conf包含serval时间的相同配置行。 使用正则表达式,我可以轻松过滤掉我想要替换的部分,但我不知道该怎么做。

这是文件的一部分:

...
[base]
name=CentOS-$releasever - Base
baseurl=http://centos.mirrors.ovh.net/ftp.centos.org/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
exclude=postfix

[updates]
name=CentOS-$releasever - Updates
baseurl=http://centos.mirrors.ovh.net/ftp.centos.org/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
exclude=postfix

[extras]
name=CentOS-$releasever - Extras
... 

这个正则表达式:

sed -n "/\[base\]/,/\[updates\]/p" /etc/yum.repos.d/CentOS-Base.repo

我可以从[base]到[updates]获取行。然后我可以修改例如exclude行。但是如何将这些行重新放回主文件中?

这是我到目前为止所做的:

# $BASE contains the lines [base] until [updates]
BASE=`sed -n "/\[base\]/,/\[updates\]/p" /etc/yum.repos.d/CentOS-Base.repo`

# Get te line that holds 'exclude' to the $EXCLUDE parameter
EXCLUDE=`echo "$BASE" | grep "exclude"`

# Modify EXCLUDE
EXCLUDE="$EXCLUDE, dovecot"

# Replace old exclude line in $BASE variable with new one
BASE=`sed "s/^exclude.*/$EXCLUDE/g" $BASE`

# Put $BASE back into /etc/yum.repos.d/CentOS-Base.repo
# ???

在这个脚本中,我试图通过多个命令实现这一点,这很好。如果只有一个替换表达式也会很好。但那当然不是必须的。

1 个答案:

答案 0 :(得分:0)

sed -i "/\[base\]/,/\[updates\]/s/^exclude.*/&, dovecot/"

sed命令由可选地址,命令和命令的任何参数组成。地址(如果存在)是指示行号的单个表达式或标识要应用命令的行的单行模式,或者是指示开始和结束行号或模式的一对逗号分隔表达式。命令的应用范围。

您之前的sed脚本("/\[base\]/,/\[updates\]/p")使用p(打印)命令,地址范围为/\[base\]//\[updates\]/

您可以将s(替代)命令应用于同一范围,以exclude.*替换&, dovecot(排除后跟任何内容 - 但吞噬其余部分) (替换字符串中的&表示匹配的所有内容。)

如果您需要在该地址范围内执行更复杂的操作,可以使用{ sed命令 - 这将打开一个以}命令终止的命令块。这可以让你做if / else块之类的事情,所以你可以这样做:

sed -i -e "/\[base\]/,/\[updates\]/{" \
        -e "/\[base\]/h" \
        -e "s/^exclude=.*/&, dovecot/" \
        -e "/^exclude=/h" \
        -e "/\[updates\]/{" \
            -e "x" \
            -e "/^exclude=/b e" \
            -e "i \
exclude=dovecot" \
            -e ": e" \
            -e "x" \
        -e "}" \
    -e "}" /etc/yum.repos.d/...

这个大毛茸茸的sed脚本执行以下操作:

  • 脚本中的所有内容都在[base][updates]行之间运行。
  • [base]行或任何以exclude=开头的行都会被放入" hold"缓冲区(通过h命令)
  • 任何以exclude=开头的行都会附加, dovecot
  • 看到[updates]时:
    • 临时恢复hold缓冲区(通过x命令将当前行交换为hold缓冲区)
    • 检查缓冲区以查看它是否以exclude=
    • 开头
    • 如果是,请跳过下一行,将分支(b}分支到标签e
    • 如果它没有(因为我们没有跳过),请插入行exclude=dovecot
    • 标签e后(通过命令:)......
    • 再次交换当前行和hold缓冲区(再次通过x

换句话说:任何exclude=行都会附加, dovecot个;如果未看到exclude=行,则会在结尾添加新的exclude=dovecot行。

请注意,从/\[base\]/转到/^$/可能更有用,如果您可以保证每个块末尾的空行(通常是这种情况),在这种情况下,您将更新第一个-e表达式以及将-e "/\[updates\]/{"更改为-e '/^$/'{(还请注意引号的更改,以便$不会被shell解析)。