Board logo

标题: [文本处理] 求批处理 提取文本中每行最末尾的中括号及其内部字符 [打印本页]

作者: anjohnlee    时间: 2014-10-15 10:07     标题: 求批处理 提取文本中每行最末尾的中括号及其内部字符

求大神动动手指啊。
我有几百万行格式基本固定的文本如下,每行末尾一定是一个中括号及内部字符。但是行中也可能出现中括号,现在我提取每行末尾那个中括号及其内部字符,行中中括号不要。
求大神写个批处理
>  CT_875 [Chlamydia trachomatis D/UW-3/CX]
> superantigen-like protein [Staphylococcus aureus subsp. aureus str. Newman]
> tryptophanyl-tRNA [synthetase] [Salmonella enterica subsp. enterica serovar Agona str. SL483]
> AsnC [family transcriptional] regulator [Geodermatophilus obscurus DSM 43160]
> methionyl-tRNA formyltransferase [[Clostridium] saccharolyticum WM1]
作者: Batcher    时间: 2014-10-15 11:22

如果你确定行尾方括号内部没有嵌套方括号的话,可以试试这样:
  1. sed "s/.*\(\[[^][]\+\]\)$/\1/" a.txt > b.txt
复制代码

作者: terse    时间: 2014-10-15 17:37

回复 1# anjohnlee
一楼数据最后行 最后结果是什么 “methionyl-tRNA formyltransferase [[Clostridium] saccharolyticum WM1]”
是希望得到  “[Clostridium] saccharolyticum WM1”    还是希望最后结果  ‘saccharolyticum WM1“
作者: Batcher    时间: 2014-10-15 19:32

回复 3# terse


    楼主说最后一行是他弄错了。800万行,2楼代码耗时30分钟左右(他当时没有精确计时)。
作者: terse    时间: 2014-10-15 21:23

来个GAWK
  1. gawk -F[ "{print FS$NF}" a.txt >b.txt
复制代码

作者: CrLf    时间: 2014-10-15 21:56

本帖最后由 CrLf 于 2014-10-15 23:20 编辑

实测用 grep 更快些,大概是支持双向预查的正则要比替换来得快捷:
  1. grep -o -P "(?<=\[)[^\[\]]+?(?=][^\[\]]*$)" a.txt>b.txt
复制代码
测试 400 万行文本 31 秒,2 楼的 sed 方案是 77 秒,不知道楼主的测试背景是什么,为什么竟然要半个小时...
发现理解错了,楼主是要求保留括号的,那就是这样:
  1. grep -o -P "\[[^\[\]]+\]$" a.txt>b.txt
复制代码
或者这样:
  1. grep -o -e "\[[^]\[]\{1,\}\]$" a.txt>b.txt
复制代码

作者: DAIC    时间: 2014-10-15 23:15

来一个可以兼容一对嵌套方括号的
  1. sed "s/.*\(\[[^][]*\[\+[^][]*\]\+[^][]*\]\)$/\1/" a.txt | sed "s/.*\(\[[^][]\+\]\)$/\1/"
复制代码
写的比较挫,有时间再想想如何优化。
作者: CrLf    时间: 2014-10-15 23:42

本帖最后由 CrLf 于 2014-10-15 23:43 编辑

用 powershell 来一个 .net 特色的正则,平衡组匹配最大的闭合 []:
  1. type a.txt | %{
  2.    if($_ -match '\[((?<test>\[)|(?<-test>\])|[^\[\]])*(?(test)(?!))\]$') {
  3.       $matches[0]
  4.    }
  5. }
复制代码

作者: xxpinqz    时间: 2014-10-16 14:56

来瞻仰下诸位大神。。。。
作者: terse    时间: 2014-10-16 19:37

本帖最后由 terse 于 2014-10-16 19:39 编辑

这里效率上还是SED略逊 grep 确实高
gwaK 直接分隔符 不处理嵌套 无嵌套的话和 grep 有一比
  
grep
  1. grep -o -P "\[([^\[\]]|(?R))*\]" a.txt
复制代码
SED
  1. sed -r "s/.*(\[([^][]+|\[[^][]+\])+\])$/\1/" a.txt
复制代码

作者: CrLf    时间: 2014-10-16 21:46

回复 10# terse


    原来 perl 正则还有 (?R) 的用法,我特么一直以为平衡组是 .net 独有的,才知道 perl 也支持,不过是叫递归组




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2