首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优化shell脚本(bash)以提高性能

优化shell脚本(bash)以提高性能
EN

Stack Overflow用户
提问于 2013-05-13 14:01:08
回答 3查看 4.2K关注 0票数 0

我有一个用于处理文本文件的bash脚本:

代码语言:javascript
复制
#/bin/bash

dos2unix sourcefile.txt

cat sourcefile.txt | grep -v '\/' | grep -v '\-\-' | grep -v '#' | grep '[A-Za-z]\*' > modified_sourcefile.txt

mv modified_sourcefile.txt sourcefile.txt
#
# Read the sourcefile file one line by line and iterate...
#

while read line
do

 echo $line | grep -v '\/' | grep -v '\-\-' | grep -v '#'
 if [ $? -eq 0 ]
 then

   # echo "Current Line is " $line ";"
    char1=`echo ${line:0:1}`
   # echo "1st char is " $char1

  if [ -n "$char1" ]
   # if a blank-line, neglect the line.
    then
        # echo "test passed"
        var1=`echo $line | cut -d '*' -f 1`
    var2=`echo $line | cut -d '*' -f 1`
    var3=`echo $line | cut -d - -f 1`
        var4=`echo $line | cut -d '*' -f 1`
        var5=`echo $line | cut -d '*' -f 2`
        var6=`echo $line | cut -d - -f 1`
        var7=`echo $line | cut -d '*' -f 3 `


        table1sql="INSERT IGNORE INTO table1 (id,name,active_yesno,category,description,
           last_modified_by,last_modified_date_time) SELECT ifnull(MAX(id),0)+1,'$var1',1,
           '$var2','$var3','admin',NOW() FROM table1;"

    echo $table1sql >> result.txt


    privsql="INSERT IGNORE INTO table2 (id,name,description,active_yesno,group_code,
             last_modified_by,last_modified_date_time) SELECT ifnull(MAX(id),0)+1,'$var1',
         '$var3',1,'$var2','admin',NOW() FROM table2;"

    echo $privsql >> result.txt     


    table1privmapsql="INSERT IGNORE INTO table1_table2_map (id,table1_id,table2_id,
                  last_modified_by,last_modified_date_time) SELECT ifnull(MAX(id),0)+1,
                  (select id from table1 where name='$var1'),(select id from table2 where name='$var1'),'admin',NOW() FROM table1_table2_map;"
    echo $table1privmapsql >> result.txt

        privgroupsql="INSERT IGNORE INTO table2_group (id,name,category,active_yesno,last_modified_by,
                      last_modified_date_time) SELECT ifnull(MAX(id),0)+1,'tablegrp','$pgpcode',1,'admin',NOW() FROM table2_group;"

        echo $privgroupsql >> result.txt


    privprivgrpsql="INSERT IGNORE INTO table2_table2group_map (id,table2_id,table2_group_id,
                        last_modified_by,last_modified_date_time) SELECT ifnull(MAX(id),0)+1,
                        (select id from table2 where name='$var1'),(select id from table2_group where name='tablegrp'),'admin',NOW() FROM table2_table2group_map;"
        echo $privprivgrpsql >> result.txt              

    rolesql="INSERT IGNORE INTO role (id,name,active_yesno,security_domain_id,last_modified_by,last_modified_date_time) 
                 SELECT (select ifnull(MAX(id),0)+1 from role),'$rolename',1, sd.id ,'admin',NOW() 
                 FROM security_domain sd WHERE sd.name = 'General';"

        echo $rolesql >> result.txt

    fi                  
 fi                        
done < "sourcefile.txt"

问题是sourcefile.txt有超过11000行代码。所以大约需要25分钟才能完成:-(。

有没有更好的方法呢?

Sourcefile.txt的内容:

代码语言:javascript
复制
AAA-something*LOCATION-some_where*ABC
EN

回答 3

Stack Overflow用户

发布于 2013-05-13 14:42:08

要使此脚本更快,您必须最小化对外部命令的调用,并尽可能使用bash。

  1. read this article以了解命令的无用用法。
  2. read this article以了解如何使用bash将strings.
  3. replace重复值(var1、var2、var4)分配给单个值。

在优化cut时,您可以替换

代码语言:javascript
复制
var1=`echo $line | cut -d '*' -f 1`

代码语言:javascript
复制
var1="${line%%\**}"

代码语言:javascript
复制
var5=`echo $line | cut -d '*' -f 2`

代码语言:javascript
复制
var5="${line%\**}"
var5="${var5##*\*}"

也许它不是那么容易阅读,但它的工作速度比cut快得多。

也是

代码语言:javascript
复制
 echo $line | grep -v '\/' | grep -v '\-\-' | grep -v '#'

可以替换为类似这样的内容:

代码语言:javascript
复制
 if [[ "$line" =~ ([/#]|--) ]]; then :; else 
    # all code inside "if [ $? -eq 0 ]"
 fi
票数 5
EN

Stack Overflow用户

发布于 2013-05-13 14:07:43

shell脚本天生就很慢,特别是当它们使用大量像您这样的外部命令时。最大的原因是因为产生外部进程相当慢,而且你做了很多次。

如果你真的想要高性能的处理你的数据,你应该写Perl或者Python脚本来做你需要的事情,而不会产生任何外部进程:没有dos2unix,没有grep,没有cut或者类似的东西。

Perl (和Python)也完全能够直接与数据库对话和插入数据,也不需要使用外部命令。

如果操作得当,我预测使用Perl的处理性能至少会比现在快100倍。

如果您对Perl没有意见,可以从下面这样的内容开始,然后根据自己的喜好进行调整:

代码语言:javascript
复制
#!/usr/bin/perl -w

use strict;
use warnings;

open FILE, "sourcefile.txt" or die $!;
open RESULT, ">>result.txt" or die $!;
while (my $line = <FILE>) {
    # ignore lines with /, -- or #: 
    next if $line =~ m{/|--|#};
    my ($var1, $var2, $var3, $var4, $var5) =
        ($line =~ /^(\w+)-(\w+)\*(\w+)-(\w+)\*(\w+)/);
    # ignore line if regex did not match:
    next unless $var1 and $var2 and $var3 and $var4 and $var5;
    print RESULT "some sql stmt. using $var1, $var2, etc";
    print RESULT "some other sql using $var1, $var2, etc";
    # ...
}
close RESULT;
close FILE;
票数 4
EN

Stack Overflow用户

发布于 2013-05-13 14:08:44

在优化之前,先配置文件!了解如何使用time命令。找出脚本中哪部分花费的时间最多,并将您的精力放在那里。

话虽如此,我认为拥有多次通过grep会让事情变慢一点。

这一点:

代码语言:javascript
复制
cat sourcefile.txt | grep -v '\/' | grep -v '\-\-' | grep -v '#' | grep '[A-Za-z]\*'

可以替换为以下内容:

代码语言:javascript
复制
grep '[A-Za-z]\*' sourcefile.txt | grep -v -e '\/' -e '\-\-' -e '#'
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16515699

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档