Chinaunix

标题: 文本替换求助-变量定义替换 [打印本页]

作者: bikkuri    时间: 2016-07-10 16:04
标题: 文本替换求助-变量定义替换
[ 本帖最后由 bikkuri 于 2016-07-10 16:05 编辑 ]

大家好,我有一个问题请教大家。
有两个文本如下:
第一个文本my.def:
#-----------------------DEFINITIONS-----------------------------

host1=www.sina.com.cn
host2=www.netease.com
host3=www.baidu.com

#-----------------------DEFINITIONS-----------------------------

第二个文本my.profile:
#! /bin/sh
# my.profile
host1=www.yahoo.com
host3=www.google.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

希望将第二个文本中与第一个文本中变量名相同的变量定义按照第一个文本中的内容进行更新。
希望处理后得到如下文本:
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

谢谢大家!
作者: 关阴月飞    时间: 2016-07-11 11:09
本帖最后由 关阴月飞 于 2016-07-11 11:10 编辑
  1. cat my.profile
  2. #! /bin/bash
  3. # my.profile

  4. . /ur_path/my.def   
  5. host1=${host1:-www.yahoo.com}
  6. host3=${host3:-www.google.com}
  7. host4=${host4:-www.taobao.com}

  8. test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
  9. for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done
复制代码

作者: 关阴月飞    时间: 2016-07-11 11:12
  1. cat my.profile
  2. #! /bin/sh
  3. # my.profile

  4. . /ur_path/my.def
  5. host1=${host1:-www.yahoo.com}
  6. host3=${host3:-www.google.com}
  7. host4=${host4:-www.taobao.com}

  8. test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
  9. for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done
复制代码

作者: sunzhiguolu    时间: 2016-07-11 11:48
  1. perl -i'.bak' -F/=/ -ne '$k=$F[0];$v=$F[-1];if(@ARGV){$h{$k}=$v if(@F==2);next}s/$v/$h{$k}/ if(@F==2&&exists($h{$k}));print' a b
复制代码
$ cat b
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

作者: sunzhiguolu    时间: 2016-07-11 11:50
  1. perl -i'.bak' -F/=/ -ne '$k=$F[0];$v=$F[-1];if(@ARGV){$h{$k}=$v if(@F==2);next}s/$v/$h{$k}/ if(@F==2&&exists($h{$k}));print' my.def my.profile
复制代码
$ cat my.profile
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done


作者: sunzhiguolu    时间: 2016-07-11 11:51
  1. perl -i'.bak' -F/=/ -ne '$k=$F[0];$v=$F[-1];if(@ARGV){$h{$k}=$v if(@F==2);next}s/$v/$h{$k}/ if(@F==2&&exists($h{$k}));print' my.def my.profile
复制代码
$ cat my.profile
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

作者: sunzhiguolu    时间: 2016-07-11 11:54
本帖最后由 sunzhiguolu 于 2016-07-11 11:55 编辑

我都回了好几遍了, 全都没了. 啥情况? 吃贴机啊!
作者: moperyblue    时间: 2016-07-11 12:07
本帖最后由 moperyblue 于 2016-07-13 14:56 编辑
  1. sed -r '1{x;s#.*#sed \x27/=/!d;s/\\s//g\x27 my.def#e;x};/host[0-9]+=/{G;s/([^=]+=)[^\n]*\n.*\1([^\n]*).*/\1\2/;t;P;d}' my.profile
复制代码
  1. sed '/=/!d;s/\s//g' my.def > vals

  2. while read line
  3. do
  4. key=`echo "$line"|awk -F= '{$0=$1}1'`
  5. sed -i '/'"$key"'\s*=/c '"$line"'' my.profile
  6. done < vals

  7. rm vals
复制代码

作者: hz_oracle    时间: 2016-07-11 13:18
awk -F"=" 'NR==FNR&&NF>1{a[$1]=$2}NR>FNR{if(a[$1])$2=a[$1];print $0}' my.def my.profile
作者: zy86416779    时间: 2016-07-11 22:11
本帖最后由 zy86416779 于 2016-07-11 22:13 编辑

回复 8# moperyblue
你好,又来打扰了。关于你的代码(sed '0,/=/{//h;d};//H;${g;p};d' my.def),有两点不懂,还望能够赐教。谢谢了。
第一点
0,/=/:我不太理解这个的含义。我在网上搜到了关于对0的解释,其中也含有1的解释,但是根据解释,我觉得1,/=/应该是到host3=的那一行。但是却不是,不知道是不是我理解的不对。我贴出来网上搜到的解释和实验代码
0,/regexp/
A line number of 0 can be used in an address specification like 0,/regexp/ so that sed will try to match regexp in the first input line too. In other words, 0,/regexp/ is similar to 1,/regexp/, except that if addr2 matches the very first line of input the 0,/regexp/ form will consider it to end the range, whereas the 1,/regexp/ form will match the beginning of its range and hence make the range span up to the second occurrence of the regular expression.
Note that this is the only place where the 0 address makes sense; there is no 0-th line and commands which are given the 0 address in any other way will give an error.
  1. [root@study awksed]# sed -n '0,/=/p' my.def   
  2. #-----------------------DEFINITIONS-----------------------------

  3. host1=xxxxx
  4. [root@study awksed]# sed -n '1,/=/p' my.def  
  5. #-----------------------DEFINITIONS-----------------------------

  6. host1=xxxxx
  7. [root@study awksed]#
复制代码
第二点
关于//h和//H。我在网上没有搜到//这个的含义,不知道这个是什么意思。应该不是和s/^$//里面的//含义一样吧?


   
作者: RE_HASH    时间: 2016-07-12 00:01
$>  grep host my.def|sed  's/\(host.\)=\(.\+\)/s\/\1=.\\+\/\1=\2\//'|sed -f - my.profile
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

作者: RE_HASH    时间: 2016-07-12 00:24
回复 7# sunzhiguolu

深有同感

$>  grep host my.def|sed  's/\(host.\)=\(.\+\)/s\/\1=.\\+\/\1=\2\//'|sed -f - my.profile
#! /bin/sh
# my.profile
host1=www.sina.com.cn
host3=www.baidu.com
host4=www.taobao.com
test_ping() { echo "$(ping -c 3 $1 |grep avg|cut -d "/" -f4|cut -d "." -f1)" ; }
for host in $host1 $host3 $host4; do echo "$host: $(test_ping $host)"; done

作者: RE_HASH    时间: 2016-07-12 00:34
$>  grep host my.def|sed  's/\(host.\)=\(.\+\)/s\/\1=.\\+\/\1=\2\//'|sed -f - my.profile

作者: RE_HASH    时间: 2016-07-12 00:36
回复 7# sunzhiguolu


这坛子似乎对淘宝摆渡之类的域名过敏。

   
作者: sunzhiguolu    时间: 2016-07-12 09:03
回复 17# RE_HASH
您老人家也太牛了, 竟然可以回复 7 楼的我!!!

   
作者: jcdiy0601    时间: 2016-07-12 14:29
本帖最后由 jcdiy0601 于 2016-07-12 14:35 编辑
  1. awk 'BEGIN{FS="="}NR==FNR{a[$1]=$2;next}NR>FNR{if(a[$1])print $1""FS""a[$1];else print}' 1 2
复制代码

作者: moperyblue    时间: 2016-07-12 16:27
本帖最后由 moperyblue 于 2016-07-13 12:03 编辑

回复 10# zy86416779


1.
想找第一次匹配的行  如果"="不在第一行的话 0,/=/和1,/=/效果一样,否则用0,/=/这种方式

2.
`h'
     Replace the contents of the hold space with the contents of the
     pattern space.

`H'
     Append a newline to the contents of the hold space, and then
     append the contents of the pattern space to that of the hold space.

作者: zy86416779    时间: 2016-07-13 09:45
回复 20# moperyblue
hi,我是知道h和H的含义的。我就是想知道//这个匹配的是什么呢。我做了个实验,我猜是只截取最后一行。还望能够得到比较权威的答复。
  1. [root@study awksed]# cat file
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. [root@study awksed]# sed -n '0,/5/{//p}' file
  8. 5
  9. [root@study awksed]# sed -n '0,/1/{//p}' file
  10. 1
  11. [root@study awksed]# sed -n '0,/2/{//p}' file
  12. 2
  13. [root@study awksed]# sed -n '0,/2/p' file   
  14. 1
  15. 2
  16. [root@study awksed]#
复制代码

作者: moperyblue    时间: 2016-07-13 12:23
本帖最后由 moperyblue 于 2016-07-15 14:27 编辑

info sed =>


`/REGEXP/'
     This will select any line which matches the regular expression
     REGEXP.  If REGEXP itself includes any `/' characters, each must
     be escaped by a backslash (`\').

     The empty regular expression `//' repeats the last regular
     expression match (the same holds if the empty regular expression is
     passed to the `s' command).  Note that modifiers to regular
     expressions are evaluated when the regular expression is compiled,
     thus it is invalid to specify them together with the empty regular
     expression.



sed -n 0,/5/{//p} => sed -n 0,/5/{/5/p}

// 就是上一次正则表达式的内容




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