优化shell和awk脚本

优化shell和awk脚本

我使用 shell 脚本、awk 脚本和 find 命令的组合对数百个文件执行多次文本替换。文件大小在几百字节到 20 千字节之间。

我正在寻找一种方法来加快这个脚本的速度。

我正在使用 cygwin。

shell脚本

#!/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

答案1

1) 错误处理中存在错误。如果您通过单个 xargs 传递一组文件,并且一个文件崩溃,则其他后续文件都不会得到处理。例如,如果

~/scripts/run_parser.sh file1 file2 file3 file4

运行,并且 file2 在 awk 上崩溃,file1 运行,但 file2、file3 和 file4 都不会运行。我建议使用continueexit 1不是 。

2) 您使用的是 Cygwin,由于模拟,速度会有点慢,这是没办法的。使用相同的工具,在 Linux 上速度会更快。

3)如果你能破解一些 perl,我建议你看看perl -p -i可以。Perl 语法并不比 awk 复杂多少,并且您只需要一个 perl 实例,而不需要多个 awk 实例。

除非速度非常非常慢,否则我可能会将其归咎于模拟问题。除了 perl -p hack 可以克服 awk 的一些额外 fork/execs 之外,我认为没有什么灵丹妙药。

答案2

这将在不到 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;
}

,如果输入文件大于 64kb,则输出文件将被截断为大约 64kb。

知道原因吗?

答案3

这是读取文件的缓冲区大小,更重要的是,你正在覆盖原始的文件名。一个解决方案是使用

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

并有单独的通行证

mv ${fileName}.fix ${fileName} 

在 bash 中

我也同意 Rich 的观点,Cygwin 的仿真导致它运行速度变慢。除了 Linux,根据您所在组织对非 Gnu 开源软件的容忍度,您可以尝试 David Korn 的 UWIN(适用于 Windows 的 Unix),网址为http://www2.research.att.com/sw/tools/uwin/ 另请参阅http://en.wikipedia.org/wiki/UWIN

祝你好运

相关内容