Chinaunix

标题: 急,请问如用sed替换块的内容 [打印本页]

作者: vipty    时间: 2021-09-01 17:49
标题: 急,请问如用sed替换块的内容
例如:
cat file
        location /
        {
                root /data/http/m-cj-web/official;
                index index.html index.htm;
                try_files $uri $uri/ /index.html;
                add_header Cache-Control max-age=31536000;
                if ($request_filename ~* .(htm|html)$){
                    add_header Cache-Control no-cache;
                    #add_header filename $http_user_agent;
                }
                #error_page 502 404  /tips.html;
                location /tips{
                        root /usr/local/nginx/html/;
                        index tips.html;
                }
如何替换掉中间的一段内容
                add_header Cache-Control max-age=31536000;
                if ($request_filename ~* .(htm|html)$){
                    add_header Cache-Control no-cache;
                    #add_header filename $http_user_agent;
                }

换成
                 add_header Cache-Control no-cache;
                if ($request_filename ~* .(js|cssl)$){
                    add_header Cache-Control max-age=31536000;
                }


作者: a5love3n    时间: 2021-09-02 16:13
本帖最后由 a5love3n 于 2021-09-02 16:16 编辑
  1. awk '/Cache/&&p{print "\t\t"x" "$3;print a;print "\t\t"$1" "$2" "b;p=0;next}/Cache/{x=$1" "$2" ";b=$3;p=1;next}p{gsub(/htm\|html/,"js|cssl",$0);a=$0;next}1{print $0}' 1.txt
复制代码


结果:
location /
        {
                root /data/http/m-cj-web/official;
                index index.html index.htm;
                try_files $uri $uri/ /index.html;
                add_header Cache-Control  no-cache;
                if ($request_filename ~* .(js|cssl)$){
                add_header Cache-Control max-age=31536000;
                    #add_header filename $http_user_agent;
                }
                #error_page 502 404  /tips.html;
                location /tips{
                        root /usr/local/nginx/html/;
                        index tips.html;
                }


作者: shell_1    时间: 2021-09-15 16:54
sed -r '/add_header Cache-Control/{:a;N;/\n.*}.*$/!{ba};s/.*/aaaaaaaaa/}' file

aaa替换成a\nb\nc格式
作者: vipty    时间: 2021-09-24 10:31
感谢楼上大神
作者: vipty    时间: 2021-09-24 11:01
回复 2# a5love3n

能帮忙解释下意思吗,看了好久根本看不懂啊
作者: vipty    时间: 2021-09-24 11:09
回复 3# shell_1

也是没研究懂什么意思
作者: a5love3n    时间: 2021-09-24 14:44
本帖最后由 a5love3n 于 2021-09-26 09:55 编辑

回复 5# vipty

把你的文件表上行号,方便说明
     1        location /
     2                {
     3                        root /data/http/m-cj-web/official;
     4                        index index.html index.htm;
     5                        try_files $uri $uri/ /index.html;
     6                        add_header Cache-Control max-age=31536000;
     7                        if ($request_filename ~* .(htm|html)$){
     8                            add_header Cache-Control no-cache;
     9                            #add_header filename $http_user_agent;
    10                        }
    11                        #error_page 502 404  /tips.html;
    12                        location /tips{
    13                                root /usr/local/nginx/html/;
    14                                index tips.html;
    15                        }

根据你给的例子分析,你的要求是:将第6行和第8行,第三项内容交换,第7行的 (htm|html) 替换为(js|cssl),删除掉#add开头的,也就是第9行
  1. awk '/Cache/&&p{print "\t\t"x" "$3;print a;print "\t\t"$1" "$2" "b;p=0;next}/Cache/{x=$1" "$2" ";b=$3;p=1;next}p{gsub(/htm\|html/,"js|cssl",$0);a=$0;next}1{print $0}' 1.txt
复制代码
整个处理流程如下:
处理 1-5行时:模式/Cache/&&p 模式/Cache/ 模式p都匹配不上,动作都跳过,只能匹配到模式1,因此会执行 1{print $0},也就是原样输出
处理低6行时:模式/Cache/&&p 匹配不上,跳过,模式/Cache/ 匹配成功,执行动作,x=$1" "$2" "是将“add_header Cache-Control ”这个内容,用变量x保存起来,
                   b=$3是把三项内容用变量b保存起来,p=1,是给变量p赋值为1,用作下一行的模式匹配,next是跳过后续模式和动作,直接处理下一行
处理第7行时:模式/Cache/&&p 模式/Cache/ 都匹配不上,跳过动作,模式P匹配成功(上一行处理时,P赋值为1了),执行动作,使用内置函数gsub将htm\|html替换为js|cssl
                   然后将替换后的整行内容$0用变量a保存起来,next跳过后续模式动作,继续处理下一行
处理第8行时:模式/Cache/&&p匹配成功,执行动作,print "\t\t"x" "$3拆解一下就是 “\t\t”  x “ ”  $3,2个tab,变量x(此时等于add_header Cache-Control ),“ ”(空格),$3(第8行的第三项 no-cache; )
                   print a ,输出变量a,就是第7行经过替换之后的内容
                   print "\t\t"$1" "$2" "b,2个tab,$1(第8行的第一项 add_header),“ ”(空格),$2(第8行的第二项(Cache-Control), “ ”空格,b(处理第6行时保存的第三项max-age=31536000;)
                   p=0变量p用完了,赋值为0,防止将其他行的html替换掉
处理9-15行时:同理,只能匹配到模式1,原样输出

处理第6和第八行时,写的有点繁杂,主要是为了保证通用性,使得,第六行和第8行的前2项不一致时,这个语法也可以通用,如果你能确保第六行和第8行只有第三项不一样的话,是可以简化一下的
也就是不需要用x来保存前两项的内容,直接把整行内容存储在变量中,
  1. awk '/Cache/&&p{print $0;print a;print b;p=0;next}/Cache/{b=$0;p=1;next}p{gsub(/htm\|html/,"js|cssl",$0);a=$0;next}1{print $0}'1.txt
复制代码


作者: vipty    时间: 2021-10-08 09:40
回复 7# a5love3n

果然是大神,非常感谢
作者: vipty    时间: 2021-10-08 09:45
回复 7# a5love3n

那麻烦问下,下面的这个server地址如果做成可以根据变量自动变动的需要用awk怎么做呢,sed我知道可以替换。文件里有这么一段
    upstream nat {
       server 172.20.128.240:80;
    }

比如我的环境变量设置为
server="172.20.128.240:80,172.20.128.241:80,172.20.128.242:80"
怎么可以替换成下面这个样子呢
    upstream nat {
       server 172.20.128.240:80;
       server 172.20.128.241:80;
       server 172.20.128.242:80;
    }




作者: a5love3n    时间: 2021-10-08 11:44
本帖最后由 a5love3n 于 2021-10-08 11:51 编辑

回复 9# vipty
根据你的描述做的
  1. cat 1.txt
  2. upstream nat {
  3.        server 172.20.128.240:80;
  4.     }

  5. server="172.20.128.240:80,172.20.128.241:80,172.20.128.242:80"

  6. export server

  7. awk 'BEGIN{split(ENVIRON["server"],ser,",")}/server/{for(i in ser){print "server "ser[i]";"};next}1' 1.txt
复制代码
结果如下
upstream nat {
server 172.20.128.240:80;
server 172.20.128.241:80;
server 172.20.128.242:80;
    }




作者: vipty    时间: 2021-10-08 12:10
回复 10# a5love3n

你也太厉害了吧,我用python写还要那么多行,没想到你直接一条命令解决了。
  1. import os,sys
  2. server = os.getenv('server')
  3. f = open('a','r+')
  4. s = f.readlines()
  5. ss = ''
  6. for i in server.split(','):
  7.     ss = ss + "\tserver " + i + ";\n"
  8. s[1] = ss
  9. f=open('a','w+')
  10. f.writelines(s)
  11. f.close()
复制代码



作者: vipty    时间: 2021-10-08 12:11
回复 10# a5love3n

强,我用python写了那么多行,你竟然一条命令就解决了,也太厉害了吧。import os,sys
server = os.getenv('server')
f = open('a','r+')
s = f.readlines()
ss = ''
for i in server.split(','):
    ss = ss + "\tserver " + i + ";\n"
s[1] = ss
f=open('a','w+')
f.writelines(s)
f.close()


作者: vipty    时间: 2021-10-08 12:11
回复 10# a5love3n
回复,你也太厉害了,我python实现还要写那么多行呢,没想到你一行命令就搞定了。
作者: vipty    时间: 2021-10-08 12:13
刚刚回复显示失败,就多发了几次。
作者: vipty    时间: 2021-10-08 12:16
回复 10# a5love3n

我执行的结果是这样的哦awk 'BEGIN{split(ENVIRON["server"],ser,",")}/server/{for(i in ser){print "server "ser";"};next}1' a
    upstream nat {
server 172.20.128.240:80;
server 172.20.128.241:80;
server 172.20.128.242:80;
    }
server 172.20.128.240:80;
server 172.20.128.241:80;
server 172.20.128.242:80;
        listen 80 default;
server 172.20.128.240:80;
server 172.20.128.241:80;
server 172.20.128.242:80;

还要麻烦问下怎么保存到当前文件啊,以前用filename好像有时候会出错。

作者: a5love3n    时间: 2021-10-08 13:38
本帖最后由 a5love3n 于 2021-10-08 13:53 编辑

回复 15# vipty

据我所知,awk无法修改原文件,要操作原文件的话,还是用sed吧
找到一种做法

awk 'BEGIN{split(ENVIRON["server"],ser,",")}/server/{for(i in ser){print "server "ser";">"1.txt"};next}1{print $0 >"1.txt"}' 1.txt

结果如下:
cat 1.txt
upstream nat {
server 172.20.128.240:80;
server 172.20.128.241:80;
server 172.20.128.242:80;
    }



作者: vipty    时间: 2021-10-08 14:18
回复 10# a5love3n

我知道为什么我这里会报错了我的文件里还有一个server,是不是要修改下匹配值啊,另外awk怎么保存到当前文件啊
  1.     upstream nat {
  2.        server 172.20.128.240:80;
  3.     }
  4.     server{
  5.         listen 80 default;
  6.         server_name _;
  7.         location / {
  8.             proxy_pass http://nat;
  9.             proxy_set_header Host $http_host;
  10.             proxy_redirect off;
  11.             proxy_set_header X-Real-IP $remote_addr;
  12.             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  13.             proxy_set_header  X-Forwarded-Host   $host;
  14.             proxy_set_header  X-Forwarded-Server $host;
  15.             proxy_set_header  X-Forwarded-Proto  $scheme;
  16.             proxy_connect_timeout 600;
  17.             proxy_read_timeout 600;
  18.             proxy_send_timeout 600;
  19.         }
  20.         
复制代码



作者: a5love3n    时间: 2021-10-08 14:31
本帖最后由 a5love3n 于 2021-10-12 10:15 编辑

重复,编辑掉


作者: a5love3n    时间: 2021-10-08 14:33
本帖最后由 a5love3n 于 2021-10-12 10:16 编辑

重复,编辑掉
作者: a5love3n    时间: 2021-10-08 14:35
本帖最后由 a5love3n 于 2021-10-12 10:16 编辑

重复,编辑掉
作者: a5love3n    时间: 2021-10-08 14:36
回复 17# vipty

  1. awk 'BEGIN{split(ENVIRON["server"],ser,",")}/server 1/{for(i in ser){print "\tserver "ser[i]";">"1.txt"};next}1{print $0 >"1.txt"}' 1.txt
复制代码
修改了匹配值并且保存到原文件,你替换掉所有的 1.txt 即可
作者: vipty    时间: 2021-10-08 17:07
回复 21# a5love3n

收到,非常感谢,学习到了。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2