Bash 如果输入不正确,则返回错误';不能正好有一行,否则将管道输入到下一步
我有一系列用管道链接在一起的命令:Bash 如果输入不正确,则返回错误';不能正好有一行,否则将管道输入到下一步,bash,shell,sh,Bash,Shell,Sh,我有一系列用管道链接在一起的命令: 是否应该创建一条线|期望一条线 第一个命令应该创建一行应该生成一个只有一行的输出,但在奇怪的情况下,输出可能是多行或空的 我想在这两者之间添加一个步骤,validate\u one\u line: 是否应该创建一条线|验证一条线|期望一条线 如果它的输入正好包含一行,那么validate\u one\u line将简单地输出它的输入。如果其输入包含多行或为空,则validate\u one\u line应导致整个步骤序列停止并返回错误代码 我可以使用什么命令来
是否应该创建一条线|期望一条线
第一个命令应该创建一行
应该生成一个只有一行的输出,但在奇怪的情况下,输出可能是多行或空的
我想在这两者之间添加一个步骤,validate\u one\u line
:
是否应该创建一条线|验证一条线|期望一条线
如果它的输入正好包含一行,那么validate\u one\u line
将简单地输出它的输入。如果其输入包含多行或为空,则validate\u one\u line
应导致整个步骤序列停止并返回错误代码
我可以使用什么命令来验证一行?当输入只有一行时,可以使用bash脚本检查传入的数据并调用另一个命令 以下代码在仅为1条线路中的fet时启动
cat
sh -c 'while read CMD; do [ ! -z "$LINE" ] && exit 1; LINE=$CMD; done; [ -z "$LINE" ] && exit 1; printf "%s\n" $LINE | "$0" "$@"' cat
这是怎么回事
printf
grep .... | sh -c 'while read CMD; do [ ! -z "$LINE" ] && exit 1; LINE=$CMD; done; [ -z "$LINE" ] && exit 1; printf "%s\n" $LINE | "$0" "$@"' 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 | "$0" "$@"' expects_one_line
首先,您应该认真考虑将验证代码添加到<代码>期望SuthOnSyral> <代码>。根据,每个进程都在其自己的子shell中启动,这意味着即使
validate\u one\u line
失败,您也会在expects\u one\u line
中得到一个错误,因为它将尝试在没有输入(或空行)的情况下运行。也就是说,这里有一个bash one衬里,您可以将其插入管道中进行验证:
should_create_one_line.sh | ( var="$(cat)"; [ $(echo "$var" | wc -l) -ne 1 ] && exit 1 || echo "$var") | expects_one_line.sh
这里的问题是,当验证子shell在exit 1
情况下返回时,需要一行。sh
仍然会得到一行空行。如果这对你有用,那就太好了。如果没有,最好将以下内容放在expects\u one\u line.sh的开头:
input="$(cat)"
[ $(echo "$var" | wc -l) -ne 1 ] && exit 1
这将保证在获取一行时,expected\u one\u line.sh
会正确失败,而不必担心验证输出的空行会对脚本产生什么影响
你可能会发现这篇文章很有帮助:使用阅读。下面是一个符合您规格的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"
}
笔记
“一行”假设一行后跟新行。如果您的输入可能是一个包含内容但没有换行符的文件,那么这将失败
给定像a | b
这样的管道,a
无法阻止b
运行。当a
不产生输出时,b
至少需要处理
演示:
$wc-l空一行两行
0空
1单线
两行
3总计
$justice_one_line<空;回声$?
1.
$justice_one_line
我认为最好的解决方案只是为了记录,如果一行的标准输入没有关闭/看到EOF,那么这将“挂起”在第二个读取
。此外,如果没有一行输出,这也不会阻止运行预期的一行。这只会将多行的情况转换为无行的情况(根据确切的\u one\u line
将看到的内容)。任何管道版本的验证\u one\u line
都会有相同的问题。需要在使用数据的脚本中进行验证。@EtanReisner我可以设置一个超时来防止挂起。你有什么更好的解决办法吗?至于管道的其余部分,在任何管道a | b
中,如果您只控制a
,则没有任何方法阻止b
运行@“疯狂的物理学家”是对的,但我不想仅仅理解那个答案,不。我不认为你能做得比暂停更好。从理论上讲,如果输出不包含换行符但包含数据(尽管我不知道这是否符合OPs的预期),您可能希望使用{read-r line | |[-n“$line”]}return
,以防输出不包含换行符而包含数据(尽管我不知道这是否符合OPs的预期)。如果输入错误,您是否需要防止运行expects one|line
?因为你不能用一条管道来实现这一点(正如Mad Physician的回答所指出的)。自我服务的评论upvote:)就像kojiro的回答一样,只要输入流不终止,这将“挂起”(这对OP来说可能是问题,也可能不是问题)但是如果应该创建一条线
在生成一行输出后运行很长时间,并且期望一条线
不想等待它完成,那么这就可能无法使用。我认为“一条线”的概念只能用有限时间内到达的EOF来定义。我不认为OP正在考虑由于这个原因需要一段时间的情况。完全可能。我刚刚在另一个答案中添加了这些信息,所以我认为我应该更加努力,并将其添加到这里。
$ 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