【问题标题】:How to store --exclude arguments for grep in an environment variable in a bash script如何将 grep 的 --exclude 参数存储在 bash 脚本的环境变量中
【发布时间】:2016-07-12 17:34:21
【问题描述】:

我的目标是在文件层次结构中搜索某些文本模式,不包括某些文件名模式,然后递归地将匹配的文件复制到名为 confs 的本地目录中。以下脚本完成了这项工作:

#!/bin/bash
export FEXCLUDE="{*edit,*debug,*orig,*BAK,*bak,*fcs,*NOPE,*tomcat,*full.xml,*-ha.xml}";
export SRCDIR=/opt/jboss-as-7.1.1.Final/standalone;

confshow() {
  for ii in `grep -rlZ \
  --exclude={*edit,*debug,*orig,*BAK,*bak,*fcs,*NOPE,*tomcat,*full.xml,*-ha.xml} \
  --exclude-dir={log,tmp,i2b2.war,*.log,*_history,*.old} "<datasource\|username\|password\|user-name" \
  $SRCDIR/*  | xargs -0 ls {}` ; 
    do cp --parents $ii confs; 
  done;
}

但是,排除模式可能需要频繁更新,并且可能需要与其他函数共享,因此我更喜欢将它们全部放在脚本开头声明的变量中。当我执行以下操作时,应该被排除的文件被复制到 confs 目录:

#!/bin/bash
export FEXCLUDE="{*edit,*debug,*orig,*BAK,*bak,*fcs,*NOPE,*tomcat,*full.xml,*-ha.xml}";
export SRCDIR=/opt/jboss-as-7.1.1.Final/standalone;

confshow() {
  for ii in `grep -rlZ \
  --exclude=$FEXCLUDE \
  --exclude-dir={log,tmp,i2b2.war,*.log,*_history,*.old} "<datasource\|username\|password\|user-name" \
  $SRCDIR/*  | xargs -0 ls {}` ; 
    do cp --parents $ii confs; 
  done;
}

知道如何获得所需的行为吗?或者如何查看grep 在通过$FEXCLUDE 参数时看到的内容(echo 没有显示任何错误)?

谢谢。

【问题讨论】:

  • 确实很奇怪。由于表达式不需要引号,我想知道您为什么用引号定义 FEXCLUDE 变量。应该没有。值得一试。

标签: linux bash scripting environment-variables


【解决方案1】:

大括号扩展非常适合交互式使用,但如果您正在编写脚本,只需使用编辑器快速复制必要的--exclude 选项并将它们存储在数组中。您可能已经注意到,参数扩展不会经历大括号扩展。

#!/bin/bash
# You didn't need to export these anyway, since only your script uses them
FEXCLUDE=( --exclude '*edit'
           --exclude '*debug'
           # etc
)
DEXCLUDE=( --exclude-dir log
           --exclude-dir tmp
           # etc
)
SRCDIR=/opt/jboss-as-7.1.1.Final/standalone

confshow() {
while IFS= read -d'' -r ii; do
    cp --parents "$ii" confs
done < <( grep -rlZ "${FEXCLUDE[@]}" "${DEXCLUDE[@]}" "<datasource\|username\|password\|user-name" $SRCDIR/* )

此外,使用ls 会首先破坏使用来自grep 的空分隔输出的目的。

【讨论】:

  • 这个来源没有错误,但现在没有任何内容被复制。
  • 我忘了复制实际的搜索模式。
  • @chepner:在这种情况下有什么理由使用大写的变量名吗?
  • @l'L'l 不;我只是按照原始代码。小写会更好,因为大写在技术上是由 shell 保留的。
  • @chepner:这就是我的意思,因为我已经看到它在这里提到了很多,除非必要(出口等),否则不要使用大写名称。这是有道理的,尽管它确实与此处提到的内容有些矛盾:tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html。它或多或少表明您可以使用任何一种,所以我不确定该相信什么。
【解决方案2】:

我知道这会引起皱眉,但这可以通过使用 eval 来解决,并且它可能不会带来通常的风险,因为我们在 --exclude= 参数中使用模式。

#!/bin/bash

fexclude='{*edit,*debug,*orig,*BAK,*bak,*fcs,*NOPE,*tomcat,*full.xml,*-ha.xml}'
dexclude='{log,tmp,i2b2.war,*.log,*_history,*.old}'
srcdir=/opt/jboss-as-7.1.1.Final/standalone

confshow() {
  eval grep -rlZ \
    --exclude="$fexclude" \
    --exclude-dir="$dexclude" \
    "<datasource\|username\|password\|user-name" \
    $srcdir/* | xargs -0 -I {} cp --parents '{}' confs
  done
}

【讨论】:

  • 我从这两个答案中学到了很多东西,非常感谢你们俩。这个答案最终成为了一个有效的答案。
猜你喜欢
  • 2015-08-06
  • 2022-01-17
  • 2021-07-04
  • 1970-01-01
  • 2017-02-03
  • 2011-03-05
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
相关资源
最近更新 更多