首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用gnu-parallel加速grep和awk

使用gnu-parallel加速grep和awk
EN

Stack Overflow用户
提问于 2014-11-18 18:33:37
回答 3查看 875关注 0票数 2

我希望使用强大的gnu并行工具来加速两行grep和awk代码,但使用简单的语法,它会崩溃或循环到无限。非常感谢您的帮助!

正常代码:

代码语言:javascript
复制
for FILENAME in `cat FileList.tmp`
do
  echo "Bearbeite $FILENAME ..."
  FILE_BASENAME=`echo ${FILENAME##*/}`
  grep -v "^t=[0-9]*.[0-9]*\&\-$" ${FILENAME} > ${INPUT}/cleaned/${FILE_BASENAME}.tmp
  awk '{ if (gsub("t=|r=|i=|d=|ip=|ua=|uc=|um=|ud=|pc=|la=|lo=|do=|dm=|c=","")) print; else print}' \
      ${INPUT}/cleaned/${FILE_BASENAME}.tmp > ${INPUT}/cleaned/${FILE_BASENAME}
  rm -f ${INPUT}/cleaned/${FILE_BASENAME}.tmp
done

并行尝试:

代码语言:javascript
复制
[...]  
parallel -j100 --pipe grep -v "^t=[0-9]*.[0-9]*\&\-$" | awk '{s = s + $1} END {print s, s/NR}' ${FILENAME} > ${INPUT}/cleaned/${FILE_BASENAME}.tmp  
awk '{ if (gsub("t=|r=|i=|d=|ip=|ua=|uc=|um=|ud=|pc=|la=|lo=|do=|dm=|c=","")) print; else print}' \
      ${INPUT}/cleaned/${FILE_BASENAME}.tmp > ${INPUT}/cleaned/${FILE_BASENAME}
 [...]

我的想法是,我只是以错误的方式传送并行命令...

EN

回答 3

Stack Overflow用户

发布于 2014-11-18 18:37:54

以下是一些思考:

代码语言:javascript
复制
while IFS= read -r FILENAME
do
   echo "Bearbeite $FILENAME ..."
   FILE_BASENAME=${FILENAME##*/} # no need to echo
   grep -v "^t=[0-9]*.[0-9]*\&\-$" ${FILENAME} > ${INPUT}/cleaned/${FILE_BASENAME}.tmp
   awk '{ if (gsub("t=|r=|i=|d=|ip=|ua=|uc=|um=|ud=|pc=|la=|lo=|do=|dm=|c=","")) print; else print}' \
    ${INPUT}/cleaned/${FILE_BASENAME}.tmp > ${INPUT}/cleaned/${FILE_BASENAME}
   rm -f ${INPUT}/cleaned/${FILE_BASENAME}.tmp
done < FileList.tmp

  • 使用while read ... done < file而不是cat blabla。
  • 不要使用echo ${FILENAME##*/}为变量赋值,只需使用grep/awk对执行您想要完成的操作,因为它可能会得到改进。例如,下面的表达式没有多大意义。

awk '{if (gsub("t=|...|c=","")) print;else print}‘...

您需要执行以下任一操作:替换并打印该行,或者如果没有执行任何替换操作,则打印原始行。这可以通过直接说gsub(); print来完成,因为gsub()会更新$0 (这一行)的值,以防它匹配:

代码语言:javascript
复制
awk '{gsub("t=|...|c=",""); print}' ...
票数 2
EN

Stack Overflow用户

发布于 2014-11-18 19:41:46

由于fedorqui已经对您的循环的结构提出了一些观点,因此我将重点介绍grep和awk部分的组合:

代码语言:javascript
复制
awk '!(/^t=[0-9]*.[0-9]*\&\-$/) {
     gsub(/(t|r|i|d|ip|ua|uc|um|ud|pc|la|lo|do|dm|c)=/,""); print }' input > output

当模式不匹配(与grep -v相同)时,执行替换并打印结果。不会打印其他行。

在awk中,gsub修改目标(默认情况下,整个记录为$0 )并返回所做的替换次数。我删除了条件代码,因为您似乎希望打印记录,无论是否进行了任何替换。

票数 1
EN

Stack Overflow用户

发布于 2014-11-18 20:51:05

当您有一个为单个文件执行此工作的脚本时,将其转换为GNU并行通常很简单:

代码语言:javascript
复制
bearbeite() {
  FILENAME=$1
  echo "Bearbeite $FILENAME ..."
  FILE_BASENAME=`echo ${FILENAME##*/}`
  grep -v "^t=[0-9]*.[0-9]*\&\-$" ${FILENAME} > ${INPUT}/cleaned/${FILE_BASENAME}.tmp
  awk '{ if (gsub("t=|r=|i=|d=|ip=|ua=|uc=|um=|ud=|pc=|la=|lo=|do=|dm=|c=","")) print; else print}' \
    ${INPUT}/cleaned/${FILE_BASENAME}.tmp > ${INPUT}/cleaned/${FILE_BASENAME}
  rm -f ${INPUT}/cleaned/${FILE_BASENAME}.tmp
}
export -f bearbeite
parallel bearbeite :::: FileList.tmp
# or:
cat FileList.tmp | parallel bearbeite

为了避免临时文件,这应该是可行的:

代码语言:javascript
复制
bearbeite() {
  FILENAME=$1
  echo "Bearbeite $FILENAME ..."
  FILE_BASENAME=`echo ${FILENAME##*/}`
  grep -v "^t=[0-9]*.[0-9]*\&\-$" ${FILENAME} |
  awk '{ if (gsub("t=|r=|i=|d=|ip=|ua=|uc=|um=|ud=|pc=|la=|lo=|do=|dm=|c=","")) print; else print}' > ${INPUT}/cleaned/${FILE_BASENAME}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26992118

复制
相关文章

相似问题

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