2013-07-17 2 views
2

Я пытаюсь написать сценарий, который в основном работает как слова Microsoft find> replace. Сначала он запрашивает два входа от пользователя. Первый для строк, которые нужно найти, а второй для строк, чтобы заменить старые. Несмотря на то, что это довольно прямолинейно, я также хочу подсчитать количество вещей, которые нужно заменить, и повторить, чтобы пользователь подтвердил это конкретное количество замен. Как я могу это сделать? До сих пор у меня есть это как поиск> заменить функцию:Как запросить пользователя при выполнении поиска> заменить в unix

for file in `find -name '*.sdf.new'`; 
do 
    grep "$search" $file &> /dev/null 
    sed -i "s/$search/$replace/" $file 
done 

ответ

0
while read -u 3 -r -d '' file; do 
    n=$(grep -o "$search" "$file" | wc -l) 
    read -p "About to replace $n instances of '$search' in $file. OK? " ans 
    if [[ $ans == [yY]* ]]; then 
     sed -i "s|${search//|/\\\\|}|${replace//|/\\\\|}|g" "$file" 
    fi 
done 3< <(find -name '*.sdf.new' -print0) 

Там какие-то хитрые вещи происходит здесь:

  • выход из команды находки отправить на время loop на дескрипторе файла 3 и чтение использует, что fd для захвата имен файлов
    • Это необходимо, потому что в цикле есть команда чтения, чтобы взаимодействовать с u ser, который должен использовать stdin.
  • цикла, а читает из process substitution<(find -name ...) так, что ни один подоболочка не должна быть создана и для облегчения использования другого дескриптора файла.
    • в bash, когда вы говорите cmd1 | cmd2, для каждой стороны трубы создаются новые процессы bash. Это может вызвать проблемы в том, что переменные, назначенные в подоболочке, отсутствуют в текущей оболочке, а не здесь.
  • правильно обрабатывать файлы с странными именами, я использую GNU найти -print0 функцию, которая разделяет имена файлов с нулевыми байтами, а затем использовать -d '' вариант Рида.
  • grep -c подсчитывает количество линий с совпадением. grep -o pattern file | wc -l подсчитывает количество совпадений.
  • сумасшедший сценарий sed добавляет защиту в случае, если поиск или строки замены содержат ограничитель команд s. Я использую | вместо /, потому что ускорение стало еще более экстремальным.
0
check_val=`grep "$search" $file` 
if [[ "x$check_val" != "x" ]] 
then 
     read -p "replace ?" response; 
     if [[ "$response" == "y" ]] 
     then 
       sed -i "s/$search/$replace/" $file 
     fi 
fi 
+0

Если вы используете grep только для проверки наличия шаблона в файле, выполните следующие действия: 'if grep -q" $ search "" $ file "; затем '- он более эффективен в том, что он вернет успех сразу после первого матча вместо того, чтобы сканировать весь файл. Кроме того, вам не нужно хранить какой-либо вывод. –

Смежные вопросы