V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
silenceboychen
V2EX  ›  程序员

vim 正则表达式替换

  •  
  •   silenceboychen · 2021-09-23 12:17:31 +08:00 · 1647 次点击
    这是一个创建于 939 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一批类似这样的数据:

    ('526440130559344640','2',7,to_date('2020-11-18 00:00:00','yyyy-mm-dd hh24:mi:ss'),'0',null,null,to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')),
    ('526440158212390912','2',3,to_date('2020-11-18 00:00:00','yyyy-mm-dd hh24:mi:ss'),'0',null,null,to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')),
    

    如何使用正则表达式批量将里边的 to_date 这一段,

    to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')
    

    提取出里边的日期,并替换掉这一段内容

    to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')  =>  '2020-11-26 01:48:39.705'
    

    最终数据变为下边的格式

    ('526440130559344640','2',7,'2020-11-18 00:00:00','0',null,null,'2020-11-26 01:48:39.705'),('526440158212390912','2',3,'2020-11-18 00:00:00','0',null,null,'2020-11-26 01:48:39.705'),
    
    11 条回复    2021-09-24 09:42:05 +08:00
    ruchee
        1
    ruchee  
       2021-09-23 12:27:07 +08:00
    首先你需要安装一个插件:eregex,因为 Vim 自带的正则太弱了

    然后就是一个命令的事了

    :%S/^[^']*?'(\d{4}.*?)'.*$/\1/g
    ruchee
        2
    ruchee  
       2021-09-23 12:30:58 +08:00
    鉴于楼主又修改了帖子内容,新的命令如下

    :%S/to_date\(('\d{4}[^']*?'.*?)\)/\1/g
    ruchee
        3
    ruchee  
       2021-09-23 12:35:04 +08:00   ❤️ 1
    上一个命令疏忽了一点,最终解

    :%S/to_date\(('\d{4}[^']*?').*?\)/\1/g
    2i2Re2PLMaDnghL
        4
    2i2Re2PLMaDnghL  
       2021-09-23 13:00:29 +08:00
    s/todate(\('[^']\+'\),[^)]\+)/\1/g
    这个是非常特化的,如果第二个字符串里有 `)` 就会出错
    毕竟没人用 vim 自动化不是嘛(
    自动化还是 ast 求值吧。
    ETiV
        5
    ETiV  
       2021-09-23 13:04:45 +08:00 via iPhone   ❤️ 3
    是有多想不开才会用 vim 去做正则替换…

    sed -i 可以修改原始文件,带一个参数还能备份原始文件
    Kasumi20
        6
    Kasumi20  
       2021-09-23 14:33:22 +08:00
    就是,写一个 js 程序去处理不是很轻松吗
    glacial
        7
    glacial  
       2021-09-23 15:00:33 +08:00
    ```java
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    public class Example {
    public static void main(String[] args) {
    final String regex = "to_date\\((.*?),(.*?)\\)";
    final String string = "('526440130559344640','2',7,to_date('2020-11-18 00:00:00','yyyy-mm-dd hh24:mi:ss'),'0',null,null,to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')),\n"
    + "('526440158212390912','2',3,to_date('2020-11-18 00:00:00','yyyy-mm-dd hh24:mi:ss'),'0',null,null,to_date('2020-11-26 01:48:39.705','yyyy-mm-dd hh24:mi:ss')),";
    final String subst = "$1";

    final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
    final Matcher matcher = pattern.matcher(string);

    // The substituted value will be contained in the result variable
    final String result = matcher.replaceAll(subst);

    System.out.println("替换结果: " + result);
    }
    }
    ```
    HiHi
        8
    HiHi  
       2021-09-23 19:43:08 +08:00
    %s/to_date(\('[^']*'\),[^)]*)/\1/g
    jaredyam
        9
    jaredyam  
       2021-09-23 22:09:19 +08:00
    随便一个脚本语言写两句也没那么费事吧
    jaredyam
        10
    jaredyam  
       2021-09-23 22:58:54 +08:00
    刚才测试了一下 sed,似乎符合你的预期:

    sed -E 's/to_date\(([^,]*),([^,)]*)\)/\1/g' <text>

    如果没问题就加个-i,inplace 操作
    gy0624ww
        11
    gy0624ww  
       2021-09-24 09:42:05 +08:00
    其实楼主就是想问正则吧。sed vim 和脚本 都是正则的不同调用方式
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5255 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 08:39 · PVG 16:39 · LAX 01:39 · JFK 04:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.