962148150 发表于 2018-8-22 07:24:15

shell 删除奇数偶数行

  今天总结一个正则的东西匹配和替换的删除奇数行和偶数行来理解模式空间以及模式空间是如何保存、标记数据的
  删除偶数行:
  %s/\(^.*$\)\n^.*$/\1/g
  删除奇数行:
  %s/^.*$\n\(^.*$\)/\1/g
  其实这是用了一种替换命令即/ab/a/g
  g/.*$/+1d 删除偶数行
  g/.*$/d|m 这个也可以涉及到了替换、模式空间标记,
  删除偶数行的方法如下:
  ?
  1
  :g/^/+1 d
  上面用到了:gbobal命令,gbobal命令格式如下:
  ?
  1
  :global/{pattern}/{command}
  global命令实际上是分成两步执行:首先扫描指定范围内的所有行,给匹配{pattern}的行打上标记;然后依次对打有标记的行执行{command}命令,如果被标记的行在对之前匹配行的命令操作中被删除、移动或合并,则其标记自动消失,而不对该行执行{command}命令。{command}可以是一个ex命令,也可以是用|分隔的多个ex命令,这样我们就可以对被标记行,或从标记行寻址到的行进行多种不同的操作。
  上面删除偶数行的命令,先匹配所有行,然后隔行删除(其中+1用以定位于当前行的下一行)。为什么是隔行呢?因为在对第一行执行+1 d命令时删除的是第二行,而第二行虽然也被标记了,但已不存在了,因此不会执行删除第三行的命令。
  删除几数行的命令如下:
  ?
  1
  :g/^/d|m
  其中m的作用是移出偶数行的标记,防止偶数行也被删除。
  另外删除几数行偶数行,也可以用normal命令,分别为(第一个命令为几数行):
  ?
  1
  2
  :%norm jkdd
  :%norm jdd
  
  %s/\(^.*$\)\n^.*$/\1/g      vi 替换命令谁能帮忙讲一下
  全局替换所有去掉特殊符号
  \( \)   是所有内容
  ^改行开头
  ^. 开行开头的第一个字符
  * 后面跟的字符
  $ 换行
  \n 换行
  \1这个不知道啥意思...
  \1 是不 是代表第一个保存的字符串啊
  不会....
  这个正则的功能是隔行删除...
  咋实现的我不知道
  悠悠巷口 10:19:33
  \n^.*$/ 这个看不懂
  每行开头
  有点得字符
  至结尾
  那它还用\n什么作用
  .不是代表有点的字符...
  点是通配符..
  %s/\(^.*$\)\n^.*$/\1/g    vi 替换命令谁能帮忙讲一下
  %s/语法
  \(^.*$\)\n^.*$
  / 语法
  \1
  /g语法
  解释:
  正则表达式预备知识
  注意到,对于正则表达式有
  匹配 任意字符 ( 除换行符 ) .
  匹配重复零次或多次前一字符 *
  匹配集合中任意字符 [...]
  匹配不属集合 中 任意字符 [^...]
  匹配 行首、行尾 ^, $
  匹配 词首、词尾 \
  正则表达式 分组 \(...\)
  第 n 个分组内容 \n
  于是
  \1 表示第一个正则表达式分组即\(^.*$\) 我们暂将第一个正则表达式分组\(^.*$\)其记为:A
  类推,\2就应该表示第二个正则表达式分组,即 \n^.*$实际上 也应该写在括号内比较好:\(\n^.*$\) ,我们也暂将第二个正则表达式分组\n^.*$
  记为:B
  于是
  %s/\(^.*$\)\n^.*$/\1/g
  就可以写为:
  %s/AB/A/g
  即将所有AB都替换成A。
  现在我们来分别分析A和B的作用。
  A=\(^.*$\)
  抽取出来实际上是\(...\),表示正则表达式 分组,再分析括号内的^.*$,^代表行首,
  .匹配 任意字符 ( 除换行符 ) , *匹配重复零次或多次前一字符 ,$代表匹配到行尾,综合起来就是:匹配这一行
  B=\n^.*$
  解释: \n换行,^.*$同上,表示匹配这一行,综合起来就是:下一行(即上行结束后开始的另一行)。
  再于是就有:%s/AB/A/g 即将所有AB都替换成B,代入A和B各自意思得到:
  将两行(如行1和行2 )内容替换为第一行内容(即行1的内容),加上/g,就是对全文进行前述替换,也就是隔行删除,如果是从文件第一行开始进行的操作,就意味着是删除所有偶数行、保留所有奇数行操作。
  
  删除偶数行:
  %s/\(^.*$\)\n^.*$/\1/g
  删除奇数行:
  %s/^.*$\n\(^.*$\)/\1/g
  
  补充另一例子: sed 's/\(.*\)\(.\)$/\2/'
  \2就应该表示第二个正则表达式分组
  同上,也将A=/\(.*\),B=\(.\)$,表达式变为's/AB/B',将AB都替换成B 。
  分析A、B作用。
  A=/\(.*\)      抽取出来实际上是\(...\),表示正则表达式
  分组,再分析括号内的 .*,表示匹配任意零个或多个字符 ( 除换行符 )
  B=\(.\)$      括号内的 . ,表示匹配 任意字符 ( 除换行符
  ) ,括号外的$表示匹配到行尾,即表示行尾的最后一个字符;那上述的A /\(.*\)就表示该行最后一个字符前的所有字符。
  于是 sed 's/\(.*\)\(.\)$/\2/'
  作用就是:删除该行除最后一个字符外的所有字符,保留最后一个字符,也即取得该行最后一个字符。
  把语法的地方去掉看具体内容
  \(^. * $\)\n ^.*$
  匹配整个文本\(\)
  开头位置字符匹配至结尾 匹配内容为第一个字符0个或者N个 制止改行结束   之后勋章换行符再之后匹配开头的第一个字符到结束 删除一行.

页: [1]
查看完整版本: shell 删除奇数偶数行