【问题标题】:grep-ing a variable vs. a file - execution timegrep 变量与文件 - 执行时间
【发布时间】:2013-04-25 10:21:36
【问题描述】:

做了一个有趣的观察——我将 cURL 语句的输出存储在一个文本文件中,然后对某些字符串进行 grep 处理。后来我更改了代码以将输出存储到变量中。事实证明,这种变化导致我的脚本运行得更慢。这对我来说真的很反直觉,因为我一直认为 I/O 操作会比内存操作更昂贵。代码如下:

#!/bin/bash
URL="http://m.cnbc.com"
while read line; do
  UA=$line
  curl -s --location --user-agent "$UA" $URL > RAW.txt
  #RAW=`curl --location --user-agent "$UA" $URL`
  L=`grep -c -e "Advertise With Us" RAW.txt`
  #L=`echo $RAW | grep -c -e "Advertise With Us"`
  M=`grep -c -e "id='menu'><button>Menu</button>" RAW.txt`
  #M=`echo $RAW | grep -c -e "id='menu'><button>Menu</button>"`
  D=`grep -c -e "Careers" RAW.txt`
  #D=`echo $RAW | grep -c -e "Careers"`
  if [[ ( $L == 1 && $M == 0 ) && ( $D == 0) ]]
    then
      AC="Legacy"
  elif [[ ( $L == 0 && $M == 1 ) && ( $D == 0) ]]
    then
  AC="Modern"
  elif [[ ( $L == 0 && $M == 0 ) && ( $D == 1) ]]
    then
      AC="Desktop"
  else
  AC="Unable to Determine"
  fi
  echo $AC >> Results.txt
done < UserAgents.txt

注释行表示存储在变量中的方法。任何想法为什么会发生这种情况?还有什么方法可以进一步加快这个脚本的速度吗?目前处理 2000 个输入条目大约需要 8 分钟。

【问题讨论】:

  • 在您的原始版本中,RAW.txt 可能适合缓存,因此您无需为连续调用 grep 支付 I/O 损失。在您的“优化”版本中,由于管道将每次调用都提供给grep,因此您正在增加需要分叉的进程数量。但请记住,如果您想要速度,则为 2000 行中的每一行分叉多个进程是错误的方法。

标签: bash curl grep


【解决方案1】:

切普纳是正确的。每次调用cURL 只需读取一次,标记三个所需字符串中的每一个。下面是一些使用awk 的示例代码。完全未经测试:

URL="http://m.cnbc.com"
while IFS= read -r line; do
    RAW=$(curl --location --user-agent "$line" $URL)

    awk '
    /Advertise With Us/ {
        L=1
    }
    /id='\''menu'\''><button>Menu<\/button>/ {
        M=1
    }
    /Careers/ {
        D=1
    }

    END {
        if (L==1 && M==0 && D==0) {
            s = "Legacy"
        }
        else if (L==0 && M==1 && D==0) {
            s = "Modern"
        }
        else if (L==0 && M==0 && D==1) {
            s = "Desktop"
        }
        else {
            s = "Unable to Determine"
        }

        print s >> "Results.txt"
    }' "$RAW"

done < UserAgents.txt

【讨论】:

    【解决方案2】:

    您真的需要计算与grep -c 匹配的次数吗?看起来您只需要知道是否找到了匹配项。如果是这样,您可以简单地使用 bash 的内置字符串比较。

    另外,如果你在循环外写入结果文件会更快。

    尝试以下方法:

    #!/bin/bash
    URL="http://m.cnbc.com"
    while read line
    do
      UA="$line"
      RAW=$(curl -s --location --user-agent "$UA" "$URL")
      [[ $RAW == *"Advertise With Us"* ]] && L=1 || L=0
      [[ $RAW == *"id='menu'><button>Menu</button>"* ]] && M=1 || M=0
      [[ $RAW == *Careers* ]] && D=1 || D=0
    
      if (( L==1 && M==0 && D==0 ))
      then
         AC="Legacy"
      elif (( L==1 && M==1 && D==0 ))
      then
         AC="Modern"
      elif (( L==1 && M==0 && D==1 ))
      then
         AC="Desktop"
      else
         AC="Unable to Determine"
      fi
      echo "$AC" 
    done < UserAgents.txt > Results.txt
    

    【讨论】:

    • @dogbane你真的需要用 grep -c 计算匹配的数量吗?看起来您只需要知道是否找到了匹配项。
    猜你喜欢
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多