Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex sed命令替换大括号内的数据_Regex_Bash_Sed - Fatal编程技术网

Regex sed命令替换大括号内的数据

Regex sed命令替换大括号内的数据,regex,bash,sed,Regex,Bash,Sed,我有一个包含以下数据的文件: upstream fibonacci { # restservers server 10.128.0.3; # 0 server 10.128.0.5; # 1 server 10.128.0.7; # 2 server 10.128.0.8; # 3 server 10.128.0.10; # 4 } 我试图找出一个sed命令来搜索整个块,并用字符串替换它

我有一个包含以下数据的文件:

upstream fibonacci {        # restservers
        server 10.128.0.3;  # 0
        server 10.128.0.5;  # 1
        server 10.128.0.7;  # 2
        server 10.128.0.8;  # 3
        server 10.128.0.10; # 4
}  
我试图找出一个sed命令来搜索整个块,并用字符串替换它

我目前有:

sed -i -e "s/upstream[:space:]fibonacci[:space:]\{.*\}/$2/g" testfile.sh
($2是传递到此bash脚本的字符串参数)

这是我的错误

sed: -e expression #1, char 46: Invalid content of \{\}
我还在学习我的正则表达式,任何帮助都会很好。谢谢

编辑:另一个选项是使用awk(推荐)替换大括号之间的文本 这可以通过sed实现,但awk是一个更好的选择

首先,像
“s/something/$2/”
这样的sed命令是非常危险的,除非
$2
的内容被清除掉所有sed活动字符

让我们以这个示例文件为例:

$ cat file
before...
upstream fibonacci {        # restservers
        server 10.128.0.3;  # 0
        server 10.128.0.5;  # 1
        server 10.128.0.7;  # 2
        server 10.128.0.8;  # 3
        server 10.128.0.10; # 4
}  
after...
要使用awk进行更换,请执行以下操作:

$ awk -v x="Replacement"  '/upstream[[:space:]]+fibonacci[[:space:]]+\{/{f=1} !f{print} /}/{print x; f=0}' file
before...
Replacement
after...
工作原理:

  • -v x=“更换”

    这将为awk变量
    x
    分配一个字符串。请注意,使用
    x=“$2”
    是安全的,因为
    x
    是否包含awk活动字符无关紧要

  • /upstream[:space:]+fibonacci[[:space:]+\{/{f=1}

    每当我们遇到起点时,将变量
    f
    设置为1(true)

  • !f{print}

    如果
    f
    为非真,则打印当前行

  • /}/{print x;f=0}

    如果当前行包含
    }
    ,则打印
    x
    ,并将
    f
    设置回零(false)

使用sed 让我们将替换字符串定义为shell变量
r

$ r="Replacement"
以下是执行替换的sed命令:

$ sed -E ":a; /upstream[[:space:]]+fibonacci[[:space:]]+\{/{ /}/!{N;ba}; s/.*/$r/ }" file
before...
Replacement
after...
工作原理:

  • :a

    这定义了一个标签
    a

  • /upstream[:space:]+fibonacci[[:space:]+\{/

    这与起始字符串匹配。对于匹配的行,将执行以下命令:

  • /}/!{N;ba};s/*/$r/

    如果该行包含
    }
    ,那么我们将读入下一行(
    N
    )并返回标签
    a
    ba
    )。如果不向后分支,我们将用shell变量
    r
    的值替换所有模式空间

如果需要,
$r
当然可以替换为
$2

sed -E ":a; /upstream[[:space:]]+fibonacci[[:space:]]+\{/{ /}/!{N;ba}; s/.*/$2/ }" file

请注意,如果
$r
(或
$2
)包含sed活动字符,则可能会发生意外情况。例如,巧尽心思构建的值可能会导致代码写入文件系统。如果您不确定此变量是否安全,请改用awk代码。

sed不适合多行匹配。我将使用perl

use strict;

my $str = 'upstream fibonacci {        # restservers
        server 10.128.0.3;  # 0
        server 10.128.0.5;  # 1
        server 10.128.0.7;  # 2
        server 10.128.0.8;  # 3
        server 10.128.0.10; # 4
}';
my $regex = qr/^upstream\sfibonacci\s{.*}$/msp;
my $subst = '$2';

my $result = $str =~ s/$regex/$subst/rg;

print "The result of the substitution is' $result\n";
对于(带备份的)备份,您可以运行以下命令行:

perl -0777 -i.bak -pe "s/\nupstream\sfibonacci\s{.*}\s*\n/abc/smg" test.txt

sed解决方案可能是:

sed -i '/upstream[[:space:]]fibonacci[[:space:]]{/{:t;N;/}/!bt;s/.*/your_replacement_string/}' your_file_name
/upstream[:space:]]fibonacci[[:space:]{/

只有找到上游斐波那契{,才能执行下一个命令

{/{:t;N;/}/!bt;s/*/您的替换字符串/}

  • 我们首先定义一个分支标签
    :t
  • 然后我们告诉sed将下一行附加到当前行
    N
  • bt
    将分支回标签
    t
    ,并执行
    N
    命令
  • 如果找到
    }
    ,则
    bt
    不会跳回
  • 然后replace语句
    s/*/your\u replacement\u string/
    将到达

  • 默认情况下,
    sed
    命令一次只能处理一行。为了让它们处理一组连续的行,您必须在它们前面加上两个地址(并非所有
    sed
    命令都接受两个地址)

    地址可以是数字(行号),
    $
    (输入中的最后一行)或分隔的正则表达式。具有两个地址的命令行选择一个包含范围。此范围从与第一个地址匹配的第一个模式空间开始。该范围的结尾是与第二个地址匹配的下一个模式空间

    理论已经足够了,让我们编写一个
    sed
    命令:

    sed -i -e "/^upstream fibonacci/,/}/c\\
    $2" testfile.sh
    
    是的,该命令跨越两行,它没有被错误包装或出于可读性考虑

    所使用的是
    c
    ,它期望替换字符串从下一行开始。
    sed
    表达式以
    $2
    后面的引号结束

    如果shell是
    bash
    ,则可以使用
    $'\n'
    在命令中插入新行:

    sed -i -e "/^upstream fibonacci/,/}/c\ "$'\n'"$2" testfile.sh
    
    它的工作原理

    sed
    命令是
    c
    。其文档说明:

    将所选行替换为
    文本
    ,其中每个嵌入的换行符前面都有反斜杠

    它前面有两个正则表达式地址:
    /^upstream fibonacci/
    是范围的开始,
    /}/
    是范围的结束。每个范围从一行开始,该行以
    上游斐波那契
    开头,并以包含右括号(
    }
    )的起始行之后的第一行结束


    整个范围将替换为作为参数传递给
    c
    命令的文本。

    Wow,谢谢!我以前没有用过awk。我肯定会把它加入我的兵工厂。@mcdito13不客气。另外,为了比较,我刚刚用
    sed
    code更新了答案。谢谢!我以前没有尝试过perl。根据谷歌的说法,这对regex很好。肯定会学到一些。为什么你从来没有投票并接受过任何答案?你评论说他们对你很有帮助。。。
    c \
    text