正则做不到这个是吧? - V2EX
helloiac

正则做不到这个是吧?

  •  
  •   helloiac Aug 3, 2018 3637 views
    This topic created in 2842 days ago, the information mentioned may be changed or developed.

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

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

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

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

    Supplement 1    Aug 3, 2018
    此问题的应用场景是一个大约 5M 的 shell 脚本,这个 shell 脚本是一系列 sed 替换语句的集合,sed 替换规则中全部是正则。

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

    中文需要 python3,剩下的问题很简单
    rabbbit
        5
    rabbbit  
       Aug 3, 2018
    硬写成一行倒是可以 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
        6
    rabbbit  
       Aug 3, 2018
    更正
    text.replace(/(?<=<sometag>)(.*)(?=<\/sometag>)/, (str) => {return str.split('').filter((i) => { return i.trim() !== ''}).join('@')});
    helloiac
        7
    helloiac  
    OP
       Aug 3, 2018
    @dreasky 谢谢。因为待匹配文本是不确定的,且有 tag 包裹这个 context 限定,所以恐怕这个方案不可行。
    ragnaroks
        8
    ragnaroks  
       Aug 3, 2018   1
    有个文本处理问题,他想到用正则来解决,现在他有两个问题了
    helloiac
        9
    helloiac  
    OP
       Aug 3, 2018
    @thedog 谢谢,APPEND 了信息,没有类似 join 的函数可用,且效率太低。
    ragnaroks
        10
    ragnaroks  
       Aug 3, 2018
    如果是每个字符后加 at 的话,我的想法是创建个 2 倍字符数的数组,遍历进去..
    helloiac
        11
    helloiac  
    OP
       Aug 3, 2018
    @CEBBCAT 是不是正则匹配出来,暂存到变量,更改后再 replace 回去呀?
    helloiac
        12
    helloiac  
    OP
       Aug 3, 2018
    @rabbbit 谢谢具体方案,用比较高级的语言的话这个方案挺好的,不过我用的是 shell,sed 也不支持零宽断言。
    yyfearth
        13
    yyfearth  
       Aug 3, 2018   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  
       Aug 3, 2018
    ```ruby
    '<tag>一些任意不定长的文字,但不包括 AT 符号和小于号</tag>'.gsub(/(?<!>)([^\@\>\<\s])/, " @\\1")

    => "<tag>一 @些 @任 @意 @不 @定 @长 @的 @文 @字 @, @但 @不 @包 @括 @A @T @符 @号 @和 @小 @于 @号</tag>"
    ```
    FanWall
        15
    FanWall  
       Aug 3, 2018 via Android
    正则很容易做到,但如果不支持环视就无法一句搞定。
    helloiac
        16
    helloiac  
    OP
       Aug 3, 2018
    @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  
       Aug 3, 2018
    @helloiac #11 输入输出流分开,加了'@'的文本直接写到另一个文件里去
    goofool
        18
    goofool  
       Aug 3, 2018
    瞎写
    sed """ /<.*>/{h; s/\(<[^\/]*>\).*/\1/p;g;s/<.*>\(.*\)<\/.*>/\1/;s/\(.\)/\1@/g; s/@$//p;g;s/.*\(<\/.*>\)/\1/p;d;}; p """ test.txt
    rabbbit
        19
    rabbbit  
       Aug 4, 2018
    @yyfearth
    你记忆力真好啊,我就记不住这么多用法细节
    hundan
        20
    hundan  
       Aug 4, 2018
    @FanWall 怎么做呢,想了想感觉用环视也做不出
    helloiac
        21
    helloiac  
    OP
       Aug 5, 2018
    @CEBBCAT 这个脚本中是一系列管道串起来的 sed, 很多行都是要运行这个的。你说的写到另一个文件里是什么意思?
    helloiac
        22
    helloiac  
    OP
       Aug 5, 2018
    @hundan
    @FanWall 是的,我也不明白用环视怎么解决。
    我认为根本问题是待匹配对象不定长,而正则替换又不能将 [量词表达的捕获组] 循环处理。
    About     Help     Advertise     Blog     API     FAQ     Solana     1389 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 54ms UTC 17:15 PVG 01:15 LAX 10:15 JFK 13:15
    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