Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如果输入不正确,则返回错误';不能正好有一行,否则将管道输入到下一步_Bash_Shell_Sh - Fatal编程技术网

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
这是怎么回事
  • 尝试读取一行,如果失败,请转至步骤5
  • 如果变量$LINE不为空,请转到步骤6
  • 在变量$line中保存行
  • 转到步骤1
  • 如果$LINE不为空,请转到步骤7
  • 退出状态代码为1的程序
  • 调用我们的程序并使用
    printf
  • 用法示例: 仅当grep找到1个匹配项时打印:

     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