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

Я ищу способ ускорить этот сценарий.

Я использую Cygwin.

Сценарий оболочки -

#!/bin/bash

if [ $# = 0 ]; then
 echo "Argument expected"
 exit 1
fi



while [ $# -ge 1 ]
do
   if [ ! -f $1 ]; then
     echo "No such file as $1"
     exit 1
   fi


  awk -f ~/scripts/parse.awk $1  > ${1}.$$

   if [ $? != 0 ]; then
      echo "Something went wrong with the script"
     rm ${1}.$$
      exit 1
   fi
mv ${1}.$$ $1
shift
done

Скрипт awk (упрощенный) -

#! /usr/bin/awk -f

/HHH.Web/{
    if ( index($0,"Email") == 0)  {
        sub(/HHH.Web/,"HHH.Web.Email");
    }
    printf("%s\r\n",$0); 
    next;
}

Командная строка

find .  -type f  | xargs ~/scripts/run_parser.sh

3 ответа3

0

1) в вашей обработке ошибок есть ошибка. Если за один проход xargs проходит группа файлов, и один файл взрывается, ни один из других последних файлов не будет обработан. например, если

~/scripts/run_parser.sh file1 file2 file3 file4

запускается, и файл2 запускается в awk, файл1 запускается, но ни файл2, ни файл3, ни файл4 не запускаются. Я предлагаю использовать continue вместо exit 1 там.

2) Вы используете Cygwin, вы будете немного медлительны из-за эмуляции, вам ничего не поделаешь. Это будет быстрее в Linux с использованием тех же инструментов.

3) Если вы можете взломать какой-нибудь perl, я бы посоветовал посмотреть, что может сделать perl -p -i . Синтаксис Perl не намного лучше, чем awk, и у вас будет один экземпляр perl против нескольких awk.

Если это не очень-очень медленно, я бы, возможно, связал это с проблемами эмуляции. Кроме хака на perl -p, чтобы преодолеть некоторые дополнительные проблемы с awk, я не думаю, что где-то есть серебряная пуля.

0

Это пройдет через все мои сотни файлов менее чем за 10 секунд. Раньше это занимало 15 минут.

find .  -type f | xargs awk -f ~/scripts/awkv2/parse.awk 

Скрипт awk (упрощенный) -

/HHH.Web/{
    if ( index($0,"Email") == 0)  {
        sub(/HHH.Web/,"HHH.Web.Email");
    }
    printf("%s\r\n",$0);  > FILENAME
    next;
}

НО, если размер входного файла превышает 64 КБ, выходной файл усекается до 64 КБ.

Есть идеи почему?

0

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

outFile= FILENAME ".fix"
printf("%s\r\n",$0);  > outFile

и иметь отдельный пропуск на

mv ${fileName}.fix ${fileName} 

в баш

Я также согласен с Ричем, что эмуляция Cygwin делает его медленнее. Помимо Linux, в зависимости от терпимости нашей организации к программному обеспечению с открытым исходным кодом, не относящимся к Gnu, вы можете попробовать UWIN (Unix для Windows) от David Korn по адресу http://www2.research.att.com/sw/tools/uwin/, также см. Http://en.wikipedia.org/wiki/UWIN.

Удачи

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .