Return 如果输入不完全是 1 行则出错,否则将输入通过管道传递到下一步

Return an error if input doesn't have exactly 1 line, otherwise pipe input to next step

我有一系列用管道链接在一起的命令:

should_create_one_line | expects_one_line

第一个命令 should_create_one_line 应该产生只有一行的输出,但在奇怪的情况下,输出可能是多行或空的。

我想在这两者之间添加一个步骤,validate_one_line

should_create_one_line | validate_one_line | expects_one_line

如果其输入恰好包含 1 行,则 validate_one_line 将简单地输出其输入。如果它的输入包含超过 1 行或为空,那么 validate_one_line 应该导致整个步骤序列停止并且 return 一个错误代码。

我可以为 validate_one_line 使用什么命令?

您可以使用bash脚本来检查传入的数据并在输入只有1行时调用另一个命令

下面的代码开始 cat 当它只出现在 1 行时

sh -c 'while read CMD; do [ ! -z "$LINE" ] && exit 1; LINE=$CMD; done; [ -z "$LINE" ] && exit 1; printf "%s\n" $LINE | "[=10=]" "$@"' cat

这是如何运作的

  1. 尝试读取一行,如果失败则转到第5步
  2. 如果变量 $LINE 不为空,转到第 6 步
  3. 在变量 $LINE 中保存行
  4. 转到第 1 步
  5. 如果 $LINE 不为空,转到第 7 步
  6. 退出状态码为1的程序
  7. 调用我们的程序并使用 printf
  8. 将我们的 $line 传递给它

用法示例:

仅当 grep 找到 1 个匹配项时打印出来:

 grep .... | sh -c 'while read CMD; do [ ! -z "$LINE" ] && exit 1; LINE=$CMD; done; [ -z "$LINE" ] && exit 1; printf "%s\n" $LINE | "[=11=]" "$@"' cat

问题张贴者示例:

 should_create_one_line | sh -c 'while read CMD; do [ ! -z "$LINE" ] && exit 1; LINE=$CMD; done; [ -z "$LINE" ] && exit 1; printf "%s\n" $LINE | "[=12=]" "$@"' expects_one_line

首先,您应该认真考虑将验证码添加到 expects_one_line。根据 this post,每个进程都在自己的子 shell 中启动,这意味着即使 validate_one_line 失败,你也会在 expects_one_line 中得到一个错误,因为它会尝试 运行 没有输入(或空行)。也就是说,这里有一个 bash one-liner,您可以将其插入管道以进行验证:

should_create_one_line.sh | ( var="$(cat)"; [ $(echo "$var" | wc -l) -ne 1 ] && exit 1 || echo "$var") | expects_one_line.sh

这里的问题是,当在exit 1 的情况下验证子shell returns 时,expects_one_line.sh 仍然会得到一个空行。如果这对你有用,那就太好了。如果没有,最好将以下内容放入 expects_one_line.sh:

的开头
input="$(cat)"
[ $(echo "$var" | wc -l) -ne 1 ] && exit 1

这将保证 expects_one_line.sh 在获取单行时正确失败,而不必想知道验证输出的空行将对脚本做什么。

您可能会发现此 post 有帮助:How to read mutliline input from stdin into variable and how to print one out in shell(sh,bash)?

使用read。这是一个符合您规格的 shell 函数:

exactly_one_line() {
    local line # Use to echo the line
    read -r line || return # Guarantee at least one line is read
    read && return 1 # Indicate failure if another line is successfully read
    echo "$line"
}

备注

  1. "One line" 假定单行后跟换行符。如果您的输入可能是一个包含内容但没有换行符的文件,那么这将失败。
  2. 给定像 a|b 这样的管道,a 无法阻止 b 来自 运行。至少,当 a 没有输出时,b 需要处理。

演示:

$ wc -l empty oneline twolines 
       0 empty
       1 oneline
       2 twolines
       3 total
$ exactly_one_line < empty; echo $?
1
$ exactly_one_line < oneline; echo $?
oneline
0
$ exactly_one_line < twolines; echo $?
1