伸手党来了:关于文本替换

  • z
    zhao414
    有这样2 个需求:

    需求 1:
    1. 在一个文件夹中有若干层的子文件夹
    2. 每个文件夹下面,都可能有若干 .md 文件
    3. 我需要把所有这些文件(包括子文件夹中的文件)中的 "#tag1" 全部替换成 "#tag2",请问用 shell 脚本应该怎么写?

    我希望未来可以重用这个脚本,比如,未来某个时候,再把 "#tag2" 全部替换成 "#tag3"

    需求 2:
    如果我只想针对当前根目录下的文件执行上述操作,脚本怎么写?
  • u
    unicon221
    就用notepad++里面的查找替换,可以指定目录下的所有文件。 iOS fly ~
  • q
    qwjhb
    everything
    搜索 全选 重命名小尾巴~
  • z
    zhao414
    回复2#unicon221
    有shell脚本么?我用的mac… iOS fly ~
  • z
    zhao414
    回复3#qwjhb
    不是文件名,是文件内容替换 iOS fly ~
  • x
    xiaokai
    VS Code可破,看看我的教程,http://vscode.10k.xyz/
  • s
    sshen012
    不用编程。用textpad, 免费。
    具体方法:
    ctrl-F5 (Search in Files),选*.md文件类型和你的总目录,比如d:\temp,然后搜索#tag1
    会返回列表。

    选中列表中的所有(ctrl-A就可以),右键选打开所有,然后按F8(就是替换),选在所有打开文件中替换就可以了。

    最后在文件菜单中,保存所有,关闭所有文件。

    整个操作不算太复杂吧。
    (没注意看4楼说了Mac机。那算了。方法保留,windows下可用)。
  • c
    chaos
    sed -i "s/要找查找的文本/替换后的文本/g" `grep -rl "要找查找的文本" /任意文件夹`
  • c
    chaos
    请善用搜索,随便搜一下,结果很多,比如

    sed和grep配合

    命令:sed -i s/yyyy/xxxx/g `grep yyyy -rl --include="*.txt" ./`

    作用:将当前目录(包括子目录)中所有txt文件中的yyyy字符串替换为xxxx字符串。其中,

    -i 表示操作的是文件,``括起来的grep命令,表示将grep命令的的结果作为操作文件。

    s/yyyy/xxxx/表示查找yyyy并替换为xxxx,后面跟g表示一行中有多个yyyy的时候,都替换,而不是仅替换第一个

    另外,如果不需要查找子目录,仅需要在当前目录替换,用sed命令就行了,命令如下:sed -i s/xxxx/yyyy/g ./*.txt
  • z
    zhouxl2000
    emeditor有个文件夹内替换
  • z
    zhao414
    回复9#chaos


    thanks!

    伸手党嘛,因为平时 sed 用得机会太少,不想琢磨了。
  • z
    zhao414
    回复8#chaos

    我觉得遍历的事情可以用 automator 来实现,我试试。有问题再请教
  • j
    johnking1
    subline text 每个想学电脑的都要安一个打开文件夹。批量替换。保存。
  • c
    chaos
    回复12#zhao414

    automator效率差,通用性不强
  • t
    tons
    如果不想用grep遍历,可以用for和xargs组合
    是find不是for
  • z
    zhao414
    回复14#chaos


    automator 可以直接生成finder 的快捷应用,还可以弄个简单的界面。当然,转换执行直接用脚本实现最好。
  • z
    zhao414
    回复15#tons

    thanks,我先试试单个文件夹的 sed,然后,再研究一下怎么遍历目录。
  • 盛世美颜
    马克一下
  • 虚生之忧
    用老马的textforever
  • z
    zhao414
    回复9#chaos


    macos 下 sed 命令的限制很多。
    目前的问题是:sed 不能直接支持文件名中有空格。。。。
  • j
    jmhqlw
    马克马克。HiPDA怪兽版
  • l
    lyztxcj
    技术贴,记号
  • c
    chaos
    回复20#zhao414
    反斜杠转义啊 iOS fly ~
  • z
    zhao414
    回复23#chaos


    对。但是,问题在于 grep 吐出来的是不带转义的,所以 sed 就接不上了,workflow 断了。
  • c
    chaos
    回复24#zhao414
    加引号 iOS fly ~
  • z
    zhao414
    回复25#chaos
    能基于你给的那个sed + grep的例子 具体说说怎么加引号么?
    btw macos 的sed是基于bsd的

    iOS fly ~
  • f
    fisherjams
    不用grep, for f in 'ls'; do sed…;done
  • c
    chaos
    FOLDER="/home/chaos/桌面/1/"
    FIND="456"
    REPLACE="123"


    SAVEIFS=$IFS
    IFS=$(echo -en "\n\b")

    sed -i "s/$FIND/$REPLACE/g" `grep -rl "$FIND" --include="*.md" "$FOLDER"`

    IFS=$SAVEIFS
  • c
    chaos
    只要改三个参数,再不行我也帮不了你了 iOS fly ~
  • t
    tons
    将 `grep ...` 改为 "$(grep ...)"
  • c
    chaos
    不要子目录的话直接用ls,把中间那句改成

    sed -i "s/$FIND/$REPLACE/g" `ls "$FOLDER"*.md`
  • 懒散的牛
    马克。 ios fly~
  • c
    chaos
    但是这种替换有风险
    比如你要把123替换成456
    那1123算不算
    11233算不算
    要提前想清楚
  • t
    tons
    既然是伸手党就直接拿走吧

    #!/bin/sh
    ORIG='#tag1'
    REPL='#tag2'

    find 目录 -name '*.md' | xargs -r sed -i "s/$ORIG/$REPL/g"

    如果不遍历目录将上面一行改为:
    find 目录 -maxdepth 1 -name '*.md' | xargs -r sed -i "s/$ORIG/$REPL/g"
  • s
    simvision
    好赞!
  • z
    zhao414
    回复34#tons
    思路了解了 thanks iOS fly ~
  • z
    zhao414
    回复34#tons


    做了一下针对 mac 适配性修改,在 sed -i 后面加了一对单引号

    ORIG='#tag1'
    REPL='tag2'

    find . -name '*.md' | xargs -r sed -i '' "s/$ORIG/$REPL/g"