个人理解,求真相。
先来看看这个命令吧
sed -n '/^AAAA/{:a;N;${s/\(.*BBBB[^\n]*\).*/\1/p};Ta}' a.txt
他实现的结果是 查找一个文件中 AAAA到BBBB字符串能匹配到的最后一行的所有内容
sed -n '/^AAAA/{:a;N;${s/\(.*BBBB[^\n]*\).*/\1/p};Ta}' a.txt
他实现的结果是 查找一个文件中 AAAA到BBBB字符串能匹配到的最后一行的所有内容
sed -n '/AAAA/{:a;N;${s/\(.*BBBB\)[\n]*.*/\1/p};Ta}'
a.txt 如下:
2012 aaaa
2012 bbbb
2013 cccc
2013 cccc
2014 1111
2014 2222
2014 3333
2015 5555
2015 xxxx
分解如下:
sed -n '/^2012/{
:a
N
${
s/\(.*2014[^\n]*\).*/
\1/p
}
Ta
}
1.首先第一个^2012是要匹配到以2012开头的行(如果字符串有在行中间的情况下^是可以去掉的)我个人觉得去掉效果会更好,已测 第一步的作用是让我们后面的命令知道我们已经从哪里开始来执行,当我们第一步找到第一个2012的时候,我后面就可以执行了
2.第一步我们显然匹配到了第一行:2012 aaaa 匹配到之后,我们先跳过:a,最后再说
匹配之后,我们执行了N命令。现在来看N命令的意思
N:追加下一个输入行到读取行的末尾 兵加入一个\n 存入缓冲区(pattern apace)
那么现在我们的缓冲区的内容是 2012 aaaa\n2012 bbbb
然后接着往后匹配匹配的是 ${s/\(.*2014[^\n]*\).*/\1/p}
现在来解析这个 首先${}是匹配最后一行的内容,也就是说如果缓冲区里最后一行的内容是
${s/\(.*2014[^\n]*\).*/\1/p} 那么这个命令的状态是yes的 否则是no 那么这个状态要配合后面的Ta来使用了 $最后一行是不是后面匹配的内容
现在再来说:a Ta 这是一个组合 意思是:
先建立一个标签a 如果Ta前面的命令状态是no,也是没匹配到,就返回到标签a处,如果是yes 这个命令就结束 打印出缓冲区
继续执行后面的命令,这样就达到了循环的目的。
现在我们来看,刚刚我们的缓冲区是2012 aaaa\n2012 bbbb后面的匹配当然就是匹配我们的缓冲区的最后一行数据,现在最后一行为2012 bbbb 的 ${s/\(.*2014[^\n]*\).*/\1/p} 显然不是 那么他的状态就是no
我们就又跳到了a 接着执行N,现在我们的缓冲区是2012 aaaa\n2012 bbbb 执行N后先加上\n然后加上了下一行 2012 aaaa\n2012 bbbb\n\2013 cccc
现在我们的缓冲区就是 2012 aaaa\n2012 bbbb\n\2013 cccc 然后执行后面 这一行是否匹配到了 ${s/\(.*2014[^\n]*\).*/\1/p} 显然没有 一直往下
我们最后到了2014 1111 行 在这一行我们的缓冲区是2012 aaaa\n2012 bbbb\n\2013
cccc\n....2014 1111
这时我们缓冲区的最后一行是2014 1111
他的前面是任意多的任意字符 ——符合
后面是任意多的非换行符 —— 符合
命令状态 yes
Ta循环结束 输出缓冲区内容 清空缓冲区
2012 aaaa
2012 bbbb
2013 cccc
2013 cccc
2014 1111
虽然循环结束但是匹配没有结束,seb依然要对下面的内容进行遍历
现在我们到了2014 2222 先执行了N 现在缓冲区为2014 2222\n2014 3333
然后匹配 ${s/\(.*2014[^\n]*\).*/\1/p} 符合 状态yes 循环结束
输出缓冲区2014 2222\n2014 3333
为什么我们匹配到2013 cccc的时候 就跳过了2014 1111 直接到了2014 2222
因为我们的2014 1111 已经被N所改变了结构 成为了上一行的内容 行号也跟着改变 这是一点比较抽象
然后我们接着匹配到了2015 5555 执行N 缓冲区为2015 5555\n2015 xxxx
匹配${s/\(.*2014[^\n]*\).*/\1/p} 不成立 状态no 执行Ta循环 到a 继续执行N... 后面已经没有2014了 所以 命令状态一直为no 知道结束都不会输出缓冲区了
其实这个命令的^AAAA可以用AAAA来代替 更加好用 已测
其实这个命令的^AAAA可以用AAAA来代替 更加好用 已测
大致就是这么个意思 不知道我的理解是否正确,如有错误,求指正。真心佩服原创的人。