是否可以在不使用cat的情况下有条件地“消失”外壳程序,使其成为管道? [英] Can I make a shell function in as a pipeline conditionally "disappear", without using cat?

查看:48
本文介绍了是否可以在不使用cat的情况下有条件地“消失”外壳程序,使其成为管道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个bash脚本,可以从一系列命令中生成一些文本。基于命令行选项,我想对输出进行一些验证。举一个人为的例子...

  CHECK_OUTPUT = $ 1 
...
check_output()
{
,如果[[[ $ CHECK_OUTPUT != --check; ]];然后
#不检查输出。传递并返回。
cat
return 0
fi

#在读行时检查fs根
中是否存在每行;如果[[! -e / $ line; ]];然后
echo错误:/ $ line不存在
返回1
fi
echo $ line
完成
返回0
}

ls / usr | grep‘^ b’| check_output

更好的示例: https://stackoverflow.com/a/52539364/1888983


这真的很有用,尤其是当我有多个可以通过的功能时。是的,我可以有条件地移动CHECK_OUTPUT并创建带有或不带有check_output的管道,但是我需要为每种组合写行以获得更多功能。如果有更好的方法可以动态构建管道,我想知道。


问题是猫的无用使用。是否可以避免这种情况,并使 check_output 像根本不在管道中一样?

解决方案

是的,您可以执行此操作-通过将函数设置为有条件地注入管道元素的包装器,而不是成为无条件的管道元素本身。例如:

  maybe_checked(){
if [[$ CHECK_OUTPUT!= --check; ]];然后
" $ @" #只是将参数作为命令运行,就好像我们不在这里
否则
#在进程替换中运行参数,从相同的标准输出中读取。
#...对原始代码进行了一些更改:
#IFS =停止删除前导或尾随空格
#read -r防止反斜杠被处理
本地行#避免在IFS = read -r行时修改函数
之外的$ line;做
[[-e / $ line; ]] || {echo错误:/ $ line不存在 >& 2;返回1; }
printf’%s\n’ $ line #参见https://unix.stackexchange.com/questions/65803
完成< <( $ @)
fi
}

ls / usr | may_checked grep'^ b'

上面代码的注意事项:如果 pipefail 选项,您将需要检查流程替换的退出状态,以与行为完全相同。在bash 4.3版或更高版本(IIRC)中, $?通过进程替换进行修改,以具有相关的PID,可以 $

也就是说,这也是一个用例,其中使用 cat 是可以接受的,并且我是说这是UUOC人群的持卡会员。 :)




采用约翰·库格曼(John Kugelman)关于链接问题的答案中的示例:

  maybe_sort(){
if((sort));然后
" $ @" |对
排序,否则
$ @
fi
}

may_limit(){
if [[-n $ limit]];然后
" $ @" |头-n $ limit
否则
$ @
fi
}

printf’%s\n’ $ {haikus [@]} | may_limit mayn_sort sed -e s / ^ [\t] * //’


I have a bash script that produces some text from a pipe of commands. Based on a command line option I want to do some validation on the output. For a contrived example...

CHECK_OUTPUT=$1
...
check_output()
{
    if [[ "$CHECK_OUTPUT" != "--check" ]]; then
        # Don't check the output. Passthrough and return.
        cat
        return 0
    fi

    # Check each line exists in the fs root
    while read line; do
        if [[ ! -e "/$line" ]]; then
            echo "Error: /$line does not exist"
            return 1
        fi
        echo "$line"
    done
    return 0
}

ls /usr | grep '^b' | check_output

[EDIT] better example: https://stackoverflow.com/a/52539364/1888983

This is really useful, particularly if I have multiple functions that can becomes passthroughs. Yes, I could move the CHECK_OUTPUT conditional and create a pipe with or without check_output but I'd need to write lines for each combination for more functions. If there are better ways to dynamically build a pipe I'd like to know.

The problem is the "useless use of cat". Can this be avoided and make check_output like it wasn't in the pipe at all?

解决方案

Yes, you can do this -- by making your function a wrapper that conditionally injects a pipeline element, instead of being an unconditional pipeline element itself. For example:

maybe_checked() {
  if [[ $CHECK_OUTPUT != "--check" ]]; then
    "$@" # just run our arguments as a command, as if we weren't here
  else
    # run our arguments in a process substitution, reading from stdout of same.
    # ...some changes from the original code:
    #   IFS= stops leading or trailing whitespace from being stripped
    #   read -r prevents backslashes from being processed
    local line # avoid modifying $line outside our function
    while IFS= read -r line; do
      [[ -e "/$line" ]] || { echo "Error: /$line does not exist" >&2; return 1; }
      printf '%s\n' "$line"  # see https://unix.stackexchange.com/questions/65803
    done < <("$@")
  fi
}

ls /usr | maybe_checked grep '^b'

Caveat of the above code: if the pipefail option is set, you'll want to check the exit status of the process substitution to have complete parity with the behavior that would otherwise be the case. In bash version 4.3 or later (IIRC), $? is modified by process substitutions to have the relevant PID, which can be waited for to retrieve exit status.

That said, this is also a use case wherein using cat is acceptable, and I'm saying this as a card-carying member of the UUOC crowd. :)


Adopting the examples from John Kugelman's answers on the linked question:

maybe_sort() {
    if (( sort )); then
        "$@" | sort
    else
        "$@"
    fi
}

maybe_limit() {
    if [[ -n $limit ]]; then
        "$@" | head -n "$limit"
    else
        "$@"
    fi
}

printf '%s\n' "${haikus[@]}" | maybe_limit maybe_sort sed -e 's/^[ \t]*//'

这篇关于是否可以在不使用cat的情况下有条件地“消失”外壳程序,使其成为管道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆