【问题标题】:Conditional command execution within piped sequence of commands in bashbash 中管道命令序列中的条件命令执行
【发布时间】:2012-03-23 20:24:07
【问题描述】:

抱歉,主题名称有问题(如果您在查看问题后发现更合适的标题,请随时编辑)。 代码示例等于 1000 个单词,所以我们开始:

if [ "$REGEX" != "" ]; then
        find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |                                  
        grep -E $REGEX |
        awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' | 
        while read -r line; do mv -f $line; done 
else
        find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |
        awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
        while read -r line; do mv -f $line; done
fi

代码的作用并不那么重要,我只是想找到更优雅的方式来使用“grep -E $REGEX”或不使用。我认为条件别名可以像我习惯使用 shell 一样完成这项工作,但它们在脚本中不起作用。

我可以设置一个条件,但我担心多次评估会影响性能。

有什么方法可以让代码“更优雅”?

【问题讨论】:

  • 您能更好地描述您正在寻找的输入/输出吗?
  • @CarlNorum 认为没有必要,但我会:首先找到匹配名称{status,stderr,stdout)-captured 的文件的打印路径,然后通过grep -E $REGEX 进一步过滤这些文件。 awk、sed 和读取,将这个例子:./dir/status-captured 组装成 mv ./dir/status-captured ./dir/status-expected,然后执行。

标签: linux bash shell pipe conditional-execution


【解决方案1】:

如果$REGEX 未设置或为空,则一种简单的方法是使用^(始终匹配:它表示“行首”,每行都有):

find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |
grep -E ${REGEX:-^} |
awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
while read -r line; do mv -f $line; done

就此而言,您可以将其合并为原始find

find $TEST_DIR -type f -regextype posix-extended \
     -regex '^.*(status|stderr|stdout)-captured$' \
     -regex ".*${REGEX}.*" |
awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
while read -r line; do mv -f $line; done

就此而言,您也可以将脚本的所有其余部分合并到 find 中:

find $TEST_DIR -type f -regextype posix-extended \
     -regex '^.*(status|stderr|stdout)-captured$' \
     -regex ".*${REGEX}.*" \
     -exec bash -c 'file="{}" ; mv -f "$file" "${file%-captured}-expected"' \;

【讨论】:

  • 有趣的是,第一个变体在我的测试树中表现最好。感谢您提供非常有趣的答案。
【解决方案2】:

一个非常简单的解决方案是:

test -n "$REGEX" && cmd="grep -E $REGEX"
find ... | ${cmd-cat} | awk ...

如果定义了 cmd,则在管道中使用它。否则,使用 cat 执行无操作。 你也可以这样做:

find ... |
if test -n "$REGEX"; then
  grep -E $REGEX
else
  cat
fi |
awk ...

效果完全一样。

【讨论】:

    【解决方案3】:

    这是一个略显丑陋但通用的解决方案。

    find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' \
     | if [ "$REGEX" != "" ]; then
            grep -E $REGEX; \
       else \
            cat; \
       fi \
     | awk '{print(""$1" "$1)}' \
     | sed 's/-captured$/-expected/' \
     | while read -r line; do mv -f $line; done 
    

    【讨论】:

      猜你喜欢
      • 2017-12-04
      • 2018-03-20
      • 1970-01-01
      • 1970-01-01
      • 2020-03-08
      • 2019-04-18
      • 2017-11-25
      • 1970-01-01
      • 2016-06-18
      相关资源
      最近更新 更多