Chinaunix

标题: 在文件中查找到最后一个匹配的行,然后插入一新行 [打印本页]

作者: linlone    时间: 2014-06-12 16:49
标题: 在文件中查找到最后一个匹配的行,然后插入一新行
比如文件内容是:
======================================
123
45678

999999999
Listen 8001
Listen 8002
Listen 8003
Listen 8004
Listen 8005
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================

我希望在最后一个Listen所在行的后面,插入“Listen 8006”,如何用脚本实现呢?
======================================
123
45678

999999999
Listen 8001
Listen 8002
Listen 8003
Listen 8004
Listen 8005
Listen 8006
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================
作者: 银风冷月    时间: 2014-06-12 16:59
  1. sed '/Listen 8005/aListen 8006' urfile
复制代码
:wink:
作者: li0924    时间: 2014-06-12 17:02
本帖最后由 li0924 于 2014-06-12 17:22 编辑
  1. awk 's && !/Listen/{print "Listen" s+1;s=0}/Listen/{s=$2}1' file
复制代码
OR
  1. awk '/Listen/{s=$2;print $0;next}s{print "Listen" s+1;s=0}1' file
复制代码

作者: linlone    时间: 2014-06-12 17:07
回复 2# 银风冷月


    非常好的方案,但其实我是不知道8005这个数字的,我唯一知道的是“Listen  xxxx”,只要查到最后一个Listen,然后插入“Listen 8006”即可
作者: reyleon    时间: 2014-06-12 17:12
  1. awk 'NR==FNR{if(/^Listen/)l=FNR;next}FNR==l{$0=$0"\n""Listen 8006"}1' file file
复制代码

作者: WilliBhamlll    时间: 2014-06-12 17:12
回复 4# linlone
  1. sed -n '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/p}' file
复制代码

作者: linlone    时间: 2014-06-12 17:13
回复 3# li0924


    输出成了这样:
Listen 8001
Listen8002
Listen 8002
Listen8003
Listen 8003
Listen8004
Listen 8004
Listen8005
Listen 8005
Listen8006
作者: li0924    时间: 2014-06-12 17:14
回复 7# linlone
已修改;再测试下


   
作者: linlone    时间: 2014-06-12 17:19
li0924 发表于 2014-06-12 17:02
OR



第二个的输出成这样了:
======================================
123
45678

999999999
Listen8006
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================





作者: jason680    时间: 2014-06-12 17:20
本帖最后由 jason680 于 2014-06-12 17:20 编辑

回复 1# linlone

$ awk '{if(!P)print;else s=s$0"\n"}/^[ \t]*Listen /{if(P)printf s;s="";P=1}END{printf "Listen 8006\n"s}' FILE
======================================
123
45678

999999999
Listen 8001
Listen 8002
Listen 8003
Listen 8004
Listen 8005
Listen 8006
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================
   
作者: linlone    时间: 2014-06-12 17:21
li0924 发表于 2014-06-12 17:02
OR


第一个:awk 's && !/Listen/{print "Listen" s+1;s=0}/Listen/{s=$2}1' file

成功输出:
======================================
123
45678

999999999
Listen 8001
Listen 8002
Listen 8003
Listen 8004
Listen 8005
Listen8006
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================

能解释一下为什么呢


作者: li0924    时间: 2014-06-12 17:23
本帖最后由 li0924 于 2014-06-12 17:32 编辑

回复 9# linlone
是我忽略了;现在已经改正。
  1. awk '/Listen/{s=$2;print $0;next}s{print "Listen " s+1;s=0}1' file
复制代码

作者: yinyuemi    时间: 2014-06-12 17:23
回复 1# linlone
  1. sed  -e '/Listen/{:a;n;/Listen/! i\' -e 'Listen  xxxx' -e ';ta}'
复制代码

作者: li0924    时间: 2014-06-12 17:27
回复 11# linlone
你是要思路;还是代码的语法



   
作者: todayhero    时间: 2014-06-12 17:44
@li0924

中间这个}s{起什么作用的。如何理解呢。
作者: li0924    时间: 2014-06-12 17:52
本帖最后由 li0924 于 2014-06-12 17:54 编辑

回复 15# todayhero
你是说第二判断中的s的含义?

它是这样的;起着判断的作用;在没匹配到/Listen/之前,它是没值的;所以不会执行{print "Listen " s+1;s=0}代码;
在匹配到/Listen/中;我给它赋值了为$2;
直到不匹配到/Listen/;s就是有值的;而且还是连续的中最后一个/Listen/的$2.
这样s有值则为真。就会执行print "Listen " s+1。再把s初始为0.这样下次不匹配到/Listen/时也不会执行print "Listen " s+1。

   
作者: linlone    时间: 2014-06-12 18:01
li0924 发表于 2014-06-12 17:23
回复 9# linlone
是我忽略了;现在已经改正。



这个成功了:awk '/Listen/{s=$2;print $0;next}s{print "Listen 80111";s=0}1' file

其实我的真实需求是:之前的数字没有规律,插入的数字也没有规律:
Listen 8005
Listen 8001
Listen 8002
Listen 80010
Listen 80015
Listen 800156

所以,你这个脚本是不是还可以简化?

作者: linlone    时间: 2014-06-12 18:27
WilliBhamlll 发表于 2014-06-12 17:12
回复 4# linlone


已经成功了:sed -n '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/p}' file
但只能生成新的文件,能否在源文件基础上,直接修改呢?我改成这样就会导致文件内容写了两份:
sed -i '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/}' file



作者: WilliBhamlll    时间: 2014-06-12 18:32
回复 18# linlone


    这样
  1. sed -ni '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/p}' file
复制代码

作者: linlone    时间: 2014-06-12 18:43
WilliBhamlll 发表于 2014-06-12 18:32
回复 18# linlone


这个成功写入原文件了:sed -ni '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/p}' file

从哪里能查到1h;   1!H;分别是什么意思
作者: linlone    时间: 2014-06-12 19:04
linlone 发表于 2014-06-12 18:43
这个成功写入原文件了:sed -ni '1h;1!H;${x;s/.*Listen[^\n]*\n/&Listen 8006\n/p}' file

从哪里能 ...


由于脚本里面需要用到变量,所以不得不改成双引号:sed -ni “1h;1!H;${x;s/.*$Pattern[^\n]*\n/&$NewLine\n/p}” file
提示错误:-bash: !H: event not found




作者: linlone    时间: 2014-06-12 19:22
linlone 发表于 2014-06-12 19:04
由于脚本里面需要用到变量,所以不得不改成双引号:sed -ni “1h;1!H;${x;s/.*$Pattern[^\n]*\n/&$NewL ...


改成这样就可以了:sed -ni '1h;1!H;${x;s/.*'"$Pattern"'[^\n]*\n/&'"$NewLine"'\n/p}' file



作者: yinyuemi    时间: 2014-06-12 21:18
回复 21# linlone


    !后面加空格
作者: daxuewuhen2014    时间: 2014-06-12 23:22
[root@weoweo ~]# sed 's/Listen 8005/& \nListen 8006/' 1.txt
======================================
123
45678

999999999
Listen 8001
Listen 8002
Listen 8003
Listen 8004
Listen 8005
Listen 8006
aaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbb   vvvvvvvvvvvvvvv

ccccccccccccccccccccccccccccccccccccccccccccc
======================================
作者: li0924    时间: 2014-06-13 09:02
回复 17# linlone
简化谈不上;至少可以让代码好看点,没bug;把$2换成具体的数字。
  1.     awk '/Listen/{s=1;print $0;next}s{print "Listen  ***";s=0}1' file
复制代码

作者: sncchen    时间: 2014-06-13 10:08
  1. $ tac 1.txt | sed '0,/Listen/{s/Listen.*/Listen 8006\n&/}' | tac
  2. 123
  3. 45678

  4. 999999999
  5. Listen 8001
  6. Listen 8002
  7. Listen 8003
  8. Listen 8004
  9. Listen 8005
  10. Listen 8006
  11. aaaaaaaaaaaaaaaaaaaaaaaaaa
  12. bbbbbbbb   vvvvvvvvvvvvvvv

  13. ccccccccccccccccccccccccccccccccccccccccccccc
复制代码

ref:  
http://stackoverflow.com/questio ... ccurrence-in-a-file
http://stackoverflow.com/questio ... -last-match-pattern
   
作者: liion631818    时间: 2014-06-13 10:21

  1. lee@ubuntu:~/share$ tac test.txt | sed -e 'x;/Listen/{x;p;d};x;/Listen/{h;i \
  2. Listen 8006
  3. }' | tac

复制代码

作者: 用户名注册后不能更改    时间: 2014-06-13 10:58
回复 27# liion631818

tac的话,sed中直接匹配到Listen然后i一行到它上面就可以了吧,需要如此复杂么……
作者: liion631818    时间: 2014-06-13 11:09
回复 28# 用户名注册后不能更改


    哦,不是有很多listen么?
作者: Herowinter    时间: 2014-06-13 11:19
回复 1# linlone
  1. sed  '/^Listen/{:1;n;/^Listen/b1;s/^/Listen 8006\n/}' i
  2. ======================================
  3. 123
  4. 45678

  5. 999999999
  6. Listen 8001
  7. Listen 8002
  8. Listen 8003
  9. Listen 8004
  10. Listen 8005
  11. Listen 8006
  12. aaaaaaaaaaaaaaaaaaaaaaaaaa
  13. bbbbbbbb   vvvvvvvvvvvvvvv

  14. ccccccccccccccccccccccccccccccccccccccccccccc
  15. ======================================
复制代码

作者: bikong0411    时间: 2014-06-13 12:12
sed -r ':1;N;$!b1;s/.*\nListen[^\n]*/&\nFucb\n/' urfile
作者: 用户名注册后不能更改    时间: 2014-06-13 14:40
回复 29# liion631818

那个啥,i完了q……
作者: 聆雨淋夜    时间: 2014-10-14 20:08
tac 1.txt|sed '0,/Listen/{//s/.*/Listen 8006\n&/}'|tac
作者: 聆雨淋夜    时间: 2014-10-14 20:10
tac 1.txt|sed '0,/Listen/{//i\
Listen 8006
}' |tac
作者: 李满满    时间: 2014-10-14 23:51
学生党:飘过~这个问题有人已经问了~http://bbs.chinaunix.net/thread-4157174-1-1.html
作者: fh21_xuejinlian    时间: 2016-04-19 11:16
sed -i "/$(cat file | grep Listen|tail -1)/a\Listen 8006" file
作者: zy86416779    时间: 2016-04-19 18:23
  1. [root@study study]# sed "`cat -n test.txt | grep -i listen | tail -n 1 | awk '{print $1}'`a Litsen 8006" test.txt
  2. 123
  3. 45678

  4. 999999999
  5. Listen 8001
  6. Listen 8002
  7. Listen 8003
  8. Listen 8004
  9. Listen 8005
  10. Litsen 8006
  11. aaaaaaaaaaaaaaaaaaaaaaaaaa
  12. bbbbbbbb   vvvvvvvvvvvvvvv

  13. ccccccccccccccccccccccccccccccccccccccccccccc
复制代码

作者: sunzhiguolu    时间: 2016-04-19 19:14
  1. perl -nle 'if (/\AListen\b/){$P=1;print;next}if ($P and !m/\AListen\b/){print "Listen 8006"}print' urfile
复制代码

作者: toddhai    时间: 2016-05-04 14:50
awk -vs="Listen" '{a[NR]=$1;b[NR]=$0}END{for(i=1;i<=NR;i++){print b[i];if(a[i]==s&&a[i+1]!=s)printf "Listen 8006\n"}}' file
作者: sunzhiguolu    时间: 2016-05-04 16:18
  1. perl -nle 'BEGIN{$,="\n"}{if(!/\AListen/){print splice(@a),"LISTEN 8006" if(@a);print;next}{push(@a,$_)}}' f
复制代码





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