【问题标题】:Find all files with text "example.html" and replace with "example.php" works only if no spaces are in file name仅当文件名中没有空格时,查找所有带有文本“example.html”并替换为“example.php”的文件才有效
【发布时间】:2014-01-18 10:12:33
【问题描述】:

我使用以下方法在文件中进行递归查找和替换,以更新 href 以正确指向新页面:

#!/bin/bash
oldstring='features.html'
newstring='features.php'
grep -rl $oldstring public_html/ | xargs sed -i s@"$oldstring"@"$newstring"@g

除了名称中有空格的少数文件外,它确实有效。

这不是问题,因为名称中带有空格的文件是我在测试新事物时创建的备份/副本。但我想了解如何在此查询中正确地将带空格的路径传递给 sed 命令。有人知道如何在这个“一个班轮”中纠正这个问题吗?

【问题讨论】:

    标签: bash unix sed grep xargs


    【解决方案1】:
    find public_html/ -type f -exec grep -q "$oldstring" {} \; -print0 |
        xargs -0 sed -i '' s@"$oldstring"@"$newstring"@g
    

    find 将打印grep 命令成功的所有文件名。我使用-print0 选项以NUL 字符作为分隔符来打印它们。这与xargs-0 选项一起使用,它将NUL 视为其输入的参数分隔符,而不是在空格处中断输入。

    其实你甚至不需要grepxargs,只要从find运行sed即可:

    find public_html/ -type f -exec sed -i '' s@"$oldstring"@"$newstring"@g {} +
    

    【讨论】:

    • 谢谢,看到不同的方法很有趣。
    【解决方案2】:

    这是一个惰性方法:

    grep -rl $oldstring public_html/ | xargs -d'\n' sed -i "s@$oldstring@$newstring@g"
    

    默认情况下,xargs 使用 空格 作为来自输入的参数的分隔符。所以例如如果你有两个文件,a bc,那么它将执行命令:

    sed -i 's/.../.../' a b c
    

    通过明确告诉xargs 使用换行符作为-d '\n' 的分隔符,它将正确处理a b 作为单个参数并在运行命令时引用它:

    sed -i 's/.../.../' 'a b' c
    

    我称之为 lazy 方法,因为正如@Barmar 指出的那样,如果您的文件名称中包含换行符,这将不起作用。如果您需要处理此类情况,请使用@Barmar 的方法与find ... -print0xargs -0 ...

    PS:我也把s@"$oldstring"@"$newstring"@g改成了"s@$oldstring@$newstring@g",和"s@$oldstring@$newstring@g"是等价的,但是可读性更强。

    【讨论】:

    • 对我的问题的解释+基于我的场景的简单修复,我喜欢它!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 2018-02-04
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    相关资源
    最近更新 更多