Синтаксис Sed и grep regex различается - PullRequest
0 голосов
/ 31 августа 2011

Это часть моего скрипта, который я использую для рекурсивного поиска и замены в рабочем каталоге.Резервное копирование и другие утилиты в других функциях, которые не имеют отношения к моей проблеме.

#!/bin/bash

# backup function goes here

# @param $1 The find pattern.
# @param $2 The replace pattern. 
function findAndReplace {
    bufferFile=/tmp/tmp.$$
    filesToReplace=`find . -type f | grep -vi cvs | grep -v '#'`
    sedPattern="s/$1/$2/g"
    echo "Using pattern $sedPattern"
    for f in $filesToReplace; do
        echo "sedding file $f"
        sed "$sedPattern" "$f" > "$bufferFile"
        exitCode=$?
        if [ $exitCode -ne 0 ] ; then
            echo "sed $sedPattern exited with $exitCode"
            exit 1
        fi
        chown --reference=$f $bufferFile
        mv $bufferFile $f
    done
}

backup
findAndReplace "$1" "$2"

Вот пример использования: recursive-replace.sh "function _report" "function report".

Это работает, но есть одна проблема.Он использует sed для ВСЕХ файлов в рабочем каталоге.Я бы хотел sed только те файлы, которые содержат шаблон поиска.

Затем я изменил строку:

filesToReplace=`find . -type f | grep -vi cvs | grep -v '#'`

до:

filesToReplace=`grep -rl "$1" . | grep -vi cvs | grep -v '#'`

И это тоже работает, но не для всех шаблонов поиска.Например, для шаблона \$this->report\((.*)\) получаю ошибку: grep: Unmatched ( or \(.Этот шаблон корректен для sed , но не для grep .Синтаксис регулярных выражений для grep и sed различается.Что я могу сделать?

Ответы [ 2 ]

0 голосов
/ 31 августа 2011

Почему бы не сравнить исходный и буферный файлы перед перезаписью исходного файла:

    #!/bin/bash
    # backup function goes here

    # @param $1 The find pattern.
    # @param $2 The replace pattern. 
    function findAndReplace {
        bufferFile=/tmp/tmp.$$
        filesToReplace=`find . -type f | grep -vi cvs | grep -v '#'`
        sedPattern="s/$1/$2/g"
        echo "Using pattern $sedPattern"
        for f in $filesToReplace; do
            echo "sedding file $f"
            sed "$sedPattern" "$f" > "$bufferFile"
            exitCode=$?         
            if [ $exitCode -ne 0 ] ; then
                echo "sed $sedPattern exited with $exitCode"
                exit 1
            fi
            cmp -s $f $bufferFile
            if [ $? -ne 0 ]; then
                chown --reference=$f $bufferFile
                mv $bufferFile $f
            fi
        done
    }

backup
findAndReplace "$1" "$2"
0 голосов
/ 31 августа 2011

использовать grep -E (опция "расширенного" регулярного выражения) - обычно это решает проблему.

(также иногда доступно как egrep)

Кроме того, почему бы не использовать find?

filesToReplace=`find . -name CVS -prune -o -type f -exec grep -l "$1" {} \; | grep -v '#'`

Также обратите внимание на параметр -i sed, который позволяет вносить изменения в файлы и удалять логику bufferFile / chown / mv.

...