替换嵌套花括号包围的代码块

时间:2016-07-21 15:27:51

标签: regex shell nginx awk sed

我有这个设置块:

...
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

我想用另一个块替换整个服务器块。希望使用AWK或SED。 替换为

...
    server {
        listen              80;
        listen              443 ssl;
        server_name         www.example.com;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
    }
}

我找到的正则表达式模式正在选择我需要的东西。 使用-m(多行)修饰符。使用的工具:Regex101.com

server {(?:[^}]*}[^}])*server {[\S\s]*(?=^\s{4}\}$)\s*}

2 个答案:

答案 0 :(得分:1)

这可能是你想要的:

$ cat tst.awk
braceCnt {
    if ( /{/ ) { braceCnt++ }
    if ( /}/ ) { braceCnt-- }
}
!braceCnt
/^[[:space:]]*server[[:space:]]*{/ {
    print newBlock
    braceCnt = 1
}

$ awk -v newBlock='        listen              80;
        listen              443 ssl;
        server_name         www.example.com;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;' -f tst.awk file
...
    server {
        listen              80;
        listen              443 ssl;
        server_name         www.example.com;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
    }
}

或者如果您更喜欢依靠缩进/空格而不是计算括号,这也可以:

$ cat tst.awk
inBlock && /^ {4}}/ { inBlock=0 }
!inBlock
/^[[:space:]]*server[[:space:]]*{/ { print newBlock; inBlock=1 }

或者如果您只想让右括号前的空格数与server之前的数字相匹配,而不是将其硬编码为4

$ cat tst.awk
inBlock && ($0 ~ "^[[:space:]]{"indent"}}") { inBlock=0 }
!inBlock
/^[[:space:]]*server[[:space:]]*{/ {
    indent = index($0,"s") - 1
    print newBlock; inBlock=1
}
等等......这一切都取决于你的要求......

答案 1 :(得分:0)

选择}前面有四个空格而后面没有任何内容:

/^\s{4}\}$/m