2013-10-25 2 views
1

Обратится к другому Q не делать/Как на SO, я добавил следующее к моему .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' 

, как ожидалось. Затем копирование этой команды выполняет ожидаемую операцию.

Что случилось с моей начальной функцией?

ответ

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 содержит косую черту. (Edited добавить:) Для того, чтобы исправить это, вы можете попросить Bash заменить / с \/ в тех параметрах, хотя это довольно некрасиво:

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

Есть ли возможность не исключать один знак из расширенного SED команды (например, '/' в этом примере)? – EverythingRightPlace

+0

Но плохое поведение можно смягчить, избегая этих косых черт? – brandones

+1

@brandones: Да. Я обновил свой ответ, чтобы добавить версию, которая это делает. Тем не менее, это выглядит смешно. :-П – ruakh

2

Из-за использования одинарных кавычек:

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

не будет работать, так как оболочка не будет расширять эти переменные. Используйте sed следующим образом:

sed -i "s/$2/$3/g" 
Смежные вопросы