正则做不到这个是吧? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
helloiac
V2EX    问与答

正则做不到这个是吧?

  •  
  •   helloiac 2018-08-03 12:09:46 +08:00 3278 次点击
    这是一个创建于 2636 天前的主题,其中的信息可能已经有所发展或是发生改变。

    匹配字符串: <sometag>一些任意不定长的文字,但不包括 AT 符号和小于号</sometag>

    一步将其替换为: <sometag>一 @些 @任 @意 @不 @定 @长 @的 @文 @字 @,@但 @不 @包 @括 @A@T@符 @号 @和 @小 @于 @号</sometag>

    也就是在 tag 内部的任意两个字符之间插入 @ 。

    我想了下应该是做不到的,请大家帮确认下。

    第 1 条附言    2018-08-03 13:38:07 +08:00
    此问题的应用场景是一个大约 5M 的 shell 脚本,这个 shell 脚本是一系列 sed 替换语句的集合,sed 替换规则中全部是正则。

    只考虑用正则是因为:
    1、这个脚本是由其它一堆 shell 脚本生成的,维护不是很“直接”
    2、shell 的函数功能比较弱,复杂些的也不好维护
    3、引入函数可能急剧增加运行时间
    22 条回复    2018-08-05 12:10:31 +08:00
    thedog
        1
    thedog  
       2018-08-03 12:31:13 +08:00 via Android
    当成一个列表,join 一下?不明白为什么要用正则
    jayx
        2
    jayx  
       2018-08-03 12:33:43 +08:00
    python 零宽断言匹配,然后 join()方法插入
    CEBBCAT
        3
    CEBBCAT  
       2018-08-03 12:49:37 +08:00
    正则把 sometag 匹配出来,别的事交给我 C 来做
    dreasky
        4
    dreasky  
       2018-08-03 13:11:51 +08:00
    re.sub(r'(.)', r'@\1', r'一些任意不定长的文字,但不包括 AT 符号和小于号')
    '@一 @些 @任 @意 @不 @定 @长 @的 @文 @字 @,@但 @不 @包 @括 @ @A@T@ @符 @号 @和 @小 @于 @号'

    中文需要 python3,剩下的问题很简单
    rabbbit
        5
    rabbbit  
       2018-08-03 13:23:41 +08:00
    硬写成一行倒是可以 js
    text = '<sometag>一些任意不定长的文字,但不包括 AT 符号和小于号</sometag>';
    text.replace(/(?<=<sometag>)(.*)(?=<\/sometag>)/, (str) => {return str.split('').filter(function(i) { return i.trim() !== '' ? true: false}).join('@')});
    // "<sometag>一 @些 @任 @意 @不 @定 @长 @的 @文 @字 @,@但 @不 @包 @括 @A@T@符 @号 @和 @小 @于 @号</sometag>"
    rabbbit
    &nsp;   6
    rabbbit  
       2018-08-03 13:25:45 +08:00
    更正
    text.replace(/(?<=<sometag>)(.*)(?=<\/sometag>)/, (str) => {return str.split('').filter((i) => { return i.trim() !== ''}).join('@')});
    helloiac
        7
    helloiac  
    OP
       2018-08-03 13:40:27 +08:00
    @dreasky 谢谢。因为待匹配文本是不确定的,且有 tag 包裹这个 context 限定,所以恐怕这个方案不可行。
    ragnaroks
        8
    ragnaroks  
       2018-08-03 13:42:00 +08:00   1
    有个文本处理问题,他想到用正则来解决,现在他有两个问题了
    helloiac
        9
    helloiac  
    OP
       2018-08-03 13:42:15 +08:00
    @thedog 谢谢,APPEND 了信息,没有类似 join 的函数可用,且效率太低。
    ragnaroks
        10
    ragnaroks  
       2018-08-03 13:43:22 +08:00
    如果是每个字符后加 at 的话,我的想法是创建个 2 倍字符数的数组,遍历进去..
    helloiac
        11
    helloiac  
    OP
       2018-08-03 13:44:15 +08:00
    @CEBBCAT 是不是正则匹配出来,暂存到变量,更改后再 replace 回去呀?
    helloiac
        12
    helloiac  
    OP
       2018-08-03 13:45:58 +08:00
    @rabbbit 谢谢具体方案,用比较高级的语言的话这个方案挺好的,不过我用的是 shell,sed 也不支持零宽断言。
    yyfearth
        13
    yyfearth  
       2018-08-03 13:51:45 +08:00   1
    @helloiac 正则一次找不到 但是两次应该可以做到
    先把 tag 里面的内容抓出来 然后替换里面的内容 每个字后面中间加 at (除了第一个字 每个字去买加 或者 除了最后一个 每个后面加)

    @rabbbit 都用上 箭头了 为啥还要用 return 另外可以不用 filter
    text.replace(/(?<=<sometag>)(.*)(?=<\/sometag>)/, str => str.split(/\s*/).join('@'))

    另外这个用到了最新的 ES RegExg 的功能 "?<=" 其实不用也可以
    text.replace(/(<sometag>)(.*)(?=<\/sometag>)/, (a, b, str) => b + str.split(/\s*/).join('@'))
    JmmBite
        14
    JmmBite  
       2018-08-03 13:58:19 +08:00
    ```ruby
    '<tag>一些任意不定长的文字,但不包括 AT 符号和小于号</tag>'.gsub(/(?<!>)([^\@\>\<\s])/, " @\\1")

    => "<tag>一 @些 @任 @意 @不 @定 @长 @的 @文 @字 @, @但 @不 @包 @括 @A @T @符 @号 @和 @小 @于 @号</tag>"
    ```
    FanWall
        15
    FanWall  
       2018-08-03 14:10:15 +08:00 via Android
    正则很容易做到,但如果不支持环视就无法一句搞定。
    helloiac
        16
    helloiac  
    OP
       2018-08-03 15:17:56 +08:00
    @JmmBite 在 irb 运行了一下,结果跟你的不一样。

    irb(main):004:0> '<tag>abcdefg</tag>'.gsub(/(?<!>)([^\@\>\<\s])/, " @\\1")
    => "< @t @a @g>a @b @c @d @e @f @g< @/ @t @a @g>"
    CEBBCAT
        17
    CEBBCAT  
       2018-08-03 16:25:27 +08:00
    @helloiac #11 输入输出流分开,加了'@'的文本直接写到另一个文件里去
    goofool
        18
    goofool  
       2018-08-03 18:37:03 +08:00
    瞎写
    sed """ /<.*>/{h; s/\(<[^\/]*>\).*/\1/p;g;s/<.*>\(.*\)<\/.*>/\1/;s/\(.\)/\1@/g; s/@$//p;g;s/.*\(<\/.*>\)/\1/p;d;}; p """ test.txt
    rabbbit
        19
    rabbbit  
       2018-08-04 02:46:06 +08:00
    @yyfearth
    你记忆力真好啊,我就记不住这么多用法细节
    hundan
        20
    hundan  
       2018-08-04 12:45:02 +08:00
    @FanWall 怎么做呢,想了想感觉用环视也做不出
    helloiac
        21
    helloiac  
    OP
       2018-08-05 12:06:24 +08:00
    @CEBBCAT 这个脚本中是一系列管道串起来的 sed, 很多行都是要运行这个的。你说的写到另一个文件里是什么意思?
    helloiac
        22
    helloiac  
    OP
       2018-08-05 12:10:31 +08:00
    @hundan
    @FanWall 是的,我也不明白用环视怎么解决。
    我认为根本问题是待匹配对象不定长,而正则替换又不能将 [量词表达的捕获组] 循环处理。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3518 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 10:39 PVG 18:39 LAX 03:39 JFK 06:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86