1

Referring to other Q/As on SO, I added the following to my .bashrc:

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

Oddly, it doesn't do anything. When I change it to:

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

I get

$ 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'

as expected. Copy-pasting that command then performs the expected operation.

What's wrong with my initial function?

4

2 回答 2

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"
}
于 2013-10-25T21:25:48.950 回答
2

由于使用单引号:

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

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

sed -i "s/$2/$3/g"
于 2013-10-25T21:25:05.350 回答