递归sed shell函数不做任何事情

时间:2013-10-25 21:19:00

标签: bash shell sed

参考SO上的其他Q / As,我将以下内容添加到我的.bashrc中:

function findandreplace {
    find . -type f -name "$1" -not -path "*/.git/*" -print0 | xargs -0 sed -i 's/$2/$3/g'
}

奇怪的是,它没有做任何事情。当我将其更改为:

function findandreplace {
    echo "find . -type f -name \"$1\" -not -path \"*/.git/*\" -print0 | xargs -0 sed -i 's/$2/$3/g'"
}

我得到了

$ findandreplace "*.cpp" "A.cpp" "B.cpp"
find . -type f -name "*.cpp" -not -path "*/.git/*" -print0 | xargs -0 sed -i 's/A.cpp/B.cpp/g'

正如所料。复制粘贴该命令然后执行预期的操作。

我的初始功能出了什么问题?

2 个答案:

答案 0 :(得分:4)

's/$2/$3/g'部分没有意义;单引号可防止参数扩展,因此您的实际sed脚本为s/$2/$3/g(美元符号和全部)而不是s/A.cpp/B.cpp/g。由于正则表达式中的$表示“字符串结束”(或有时称为“行尾”),$2将永远不会匹配任何内容。

要解决此问题,您可以改为使用双引号:

function findandreplace {
    find . -type f -name "$1" -not -path "*/.git/*" -print0 \
    | xargs -0 sed -i "s/$2/$3/g"
}

请注意,如果$2$3包含斜杠,则会出现这种情况。 (已编辑添加:)要解决此问题,您可以要求Bash在这些参数中将/替换为\/,但这非常难看:

function findandreplace {
    find . -type f -name "$1" -not -path "*/.git/*" -print0 \
    | xargs -0 sed -i "s/${2//\//\/}/${3//\//\/}/g"
}

答案 1 :(得分:2)

由于使用单引号:

sed -i 's/$2/$3/g'

将无效,因为shell不会扩展这些变量。像这样使用sed:

sed -i "s/$2/$3/g"