V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
dazkarieh
V2EX  ›  Linux

求批量替换的办法

  •  
  •   dazkarieh · 2019-04-07 09:30:53 +08:00 · 3683 次点击
    这是一个创建于 2084 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想检索当前目录下所有*.MD 文件的内容,如果遇到

    ![text](url)
    

    就替换为

    {{< img src="url" alt="text">}}
    

    //这里的 text 是指方括号里的任意文本,url 是指括弧里的任意链接地址,并非特指。

    试了一个大佬提供的办法

    sed -i -r 's/\!\[(.*)\]\((.*)\)/{{<img src="\1" alt="\2">}}/' *.md
    

    但是我这边报错

    sed: 1: "s/\!\[(.*)\]\((.*)\)/{{ ...": \2 not defined in the RE
    

    环境是 MacOS 系统,这要咋改?

    15 条回复    2019-04-10 22:47:22 +08:00
    geelaw
        1
    geelaw  
       2019-04-07 09:42:03 +08:00 via iPhone
    你的行动并没有代表本来的意思,因为并不是所有的 ![]() 都是图,而且有些图是有 alt 的。最简单的正确做法是用 Markdown 编译器把 Markdown 编译成 Markdown。

    当然,实际情况是你的所有 ![]() 都是图,那么这样的替换也是不安全的,因为你忘记了非贪婪匹配。

    第一种解决方法是在 macOS 上安装 GNU sed,然后用 GNU sed。

    第二种解决方法是在 macOS 上输入 man sed,查看 macOS 的 sed 如何在替换字符串里用捕获组。
    aaaaasam
        2
    aaaaasam  
       2019-04-07 09:51:19 +08:00
    s#\!\[\(.*\)\](\(.*\))#{{< img src="\1" alt="\2">}}
    Belmode
        3
    Belmode  
       2019-04-07 09:54:37 +08:00 via Android
    这个正则太简单了,sed 命令 linux 支持,不知道 mac 是啥
    dazkarieh
        4
    dazkarieh  
    OP
       2019-04-07 10:19:34 +08:00
    @aaaaasam -sh: syntax error near unexpected token `\(.*\)'
    @geelaw 谢谢您的详细耐心解答,虽然没安装成 GNU SED,但至少明白问题出在哪儿了
    @Belmode 兄嘚说的是,是我没搞明白
    xy2401
        5
    xy2401  
       2019-04-07 10:24:15 +08:00
    我运行是成功都 是不是 -i 错了?
    $ echo '#![text](url)' | sed -r 's/\!\[(.*)\]\((.*)\)/{{<img src="\1" alt="\2">}}/'
    #{{<img src="text" alt="url">}}
    dazkarieh
        6
    dazkarieh  
    OP
       2019-04-07 10:26:10 +08:00
    @xy2401 我装了 gsed,然后用下面测试成功了。

    gsed -i -r 's/\!\[(.*)\]\((.*)\)/{{<img src="\2" alt="\1">}}/' *.md
    xy2401
        7
    xy2401  
       2019-04-07 10:29:35 +08:00
    我试了一下 你的命令没问题 我是在 windows 上的 wsl 上尝试的 修改文件成功了

    我一开始 echo 然后 -i 结果报错和你一样
    echo '#![text](url)' | sed -i 's/\!\[(.*)\]\((.*)\)/{{<img src="\1" alt="\2">}}/'
    sed: -e expression #1, char 49: invalid reference \2 on `s' command's RHS
    aaaaasam
        8
    aaaaasam  
       2019-04-07 11:39:35 +08:00
    @dazkarieh s#\!\[\(.*\)\](\(.*\))#{{< img src="\1" alt="\2">}}# 少复制了一个#
    TonyLiu2ca
        9
    TonyLiu2ca  
       2019-04-07 11:43:06 +08:00
    @dazkarieh

    看看这个过程
    ```
    $ cat Test.MD
    ![text](url)
    ![Pci1]( http://aa.bb.cc)
    ![DATA1]( http://aa.bb.cc)
    ![Pci2]( http://bbb.com)
    ![]
    ![DATA_2]( http://bbb.com)
    ![( http://)
    ![]
    ( http://)
    ![] (
    http://)

    $ sed -E 's/\!\[(.*)\]\((.*:\/\/.*)(.*)\)/{{img src="\1" alt="\2\3"}}/' Test.MD
    ![text](url)
    {{img src="Pci1" alt="http://aa.bb.cc"}}
    {{img src="DATA1" alt="https://aa.bb.cc"}}
    {{img src="Pci2" alt="http://bbb.com"}}
    ![]
    {{img src="DATA_2" alt="https://bbb.com"}}
    ![( http://)
    ![]
    ( http://)
    ![] (
    http://)
    ```

    这个例子里面稍微做了一点对 url 的检测,假设符合“*://*”的格式,也就是 http://*, https://* 或 ftp://*等等,这个可能是多余,或者说并不完备,只是个例子。
    aaaaasam
        10
    aaaaasam  
       2019-04-07 11:43:16 +08:00
    @dazkarieh sed -i -r 's#\!\[\(.*\)\](\(.*\))#{{< img src="\1" alt="\2">}}#' test.md
    winglight2016
        11
    winglight2016  
       2019-04-07 16:27:52 +08:00
    牛!没想到正则还能这么玩。。。我 google 了一下:convert md to html,工具挺多的,应该能满足 lz 需求
    troyl
        12
    troyl  
       2019-04-07 16:59:52 +08:00 via iPhone
    在 Mac 下使用 sed 的 in-place replacement 要在 -i 后面加 一个额外的 '' 。这个跟 Linux 是不一样的。
    xy2401
        13
    xy2401  
       2019-04-09 23:59:20 +08:00
    问一下 lz 一个简单的问题 我今天有一个类似的需求。 有没有人帮忙解答一下
    ![text](url) --> ![text](../abcd/url) url 加一个前缀就可以了。需求很简单
    http://url.html 不要匹配。url.html 匹配。 我只要要判断 \w 文本加一个 . 即可。可是 这个. 我总是无法匹配


    $ echo '#![text](url.)' | sed -r 's/\]\((\w)/\]\(\.\.\/abcd\/\1/'
    #![text](../abcd/url.)
    $ echo '#![text](url.)' | sed -r 's/\]\((\w)\./\]\(\.\.\/abcd\/\1/'
    #![text](url.)
    xy2401
        14
    xy2401  
       2019-04-10 08:47:21 +08:00
    我 sb 了

    \w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。

    我一直记成了 \w 是匹配完整的一个单词


    # echo '#![text](url.html) #![text]( http://url.com) #![text](context/url.html)' | sed -r 's/\]\((\w*)([\.\/])/\]\(\.\.\/abcd\/\1\2/g'
    #![text](../abcd/url.html) #![text]( http://url.com) #![text](../abcd/context/url.html)
    #
    51Tao
        15
    51Tao  
       2019-04-10 22:47:22 +08:00
    find . -type f -name "*.md" -exec perl -pi -e 's#OLDSTR#NEWSTR#g' {} \;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2680 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:09 · PVG 20:09 · LAX 04:09 · JFK 07:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.