当函数从shell脚本调用here-document时,函数应该如何退出?

时间:2014-02-24 12:32:05

标签: bash shell unix cobol heredoc

我有一个COBOL程序,它应该通过shell脚本运行,并且应该接受here文档中的值。在这里的文档中,我应该调用一个函数,该函数应该让控制与退出代码异常退出。

我试过如下,但它不适合我。

这是我的COBOL计划:

   01  WW-ANS              PIC X value space. 

IRS-200.
      display "ARE THE ABOVE ANSWERS CORRECT? Y/N/E".
      Accept ws-ans.
      display "entered value is " ws-ans "<".

      IF WW-ANS  =  "E"  or "e"
         PERFORM STOP-RUN-CA.

      IF WW-ANS  NOT =  "Y" AND "N" AND "E"      
                    and "y" and "n" and "e"      
          PERFORM DISPLAY-01 THRU DISPLAY-01-EXIT
          GO  TO  IRS-200.

      IF WW-ANS  =  "Y" or "y"                   
          display "Program executed successfully"
          PERFORM STOP-RUN-CA. 
      ELSE                                       
          GO  TO  IRS-200.

DISPLAY-01.                       
      DISPLAY "value is >" WW-ANS "<".
      DISPLAY "INVALID RESPONSE".

这是我的shell脚本:

#!/bin/bash
funexit ()
{
echo "calling funexit"
exit 1
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:

输出为:

[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is  c<
value is >C<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully

当从这里调用函数文件时,COBOL程序接受值为“C”,因为在函数:它调用echo命令并考虑“调用funexit”字符串中的第一个字符,而不是退出。 / p>

从该函数中,我删除了如下所示的echo语句:

#!/bin/bash
funexit ()
{
exit 1
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:

输出为:

[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is   <
value is > <
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully.

当从这里调用函数时,COBOL程序接受该值作为空格而不是退出。

脚本应该通过一些退出代码异常退出。

5 个答案:

答案 0 :(得分:1)

这个例子看起来很人为,因为你给它两个静态输入。但是,这可能是因为这只是一个简化的例子。

我想是你想要funexit返回E以便输入意味着没有更多输入,如果有更多输入则没有。为了清楚起见,在调用 COBOL之前调用funexit脚本(并完成)

我认为您希望像这样编写shell脚本:

#!/bin/bash
funexit ()
{
  echo calling funexit 1>&2
  echo E
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)Y
:EOD:

请注意,对funexit和以下Y的调用位于同一行。这样,如果funexit没有返回任何内容,那么cobol程序就不会看到空行。如果funexit返回E(实际上是E后跟一个新行),它将看到E。

另请注意,“Calling funexit”的调试输出被重定向到标准错误;在它被发送到cobol程序之前它接受了字母C(来自“Calling”)。

最后,funexit脚本不需要退出,因为无论如何,这将在脚本结束时发生。

答案 1 :(得分:1)

@ANR;

使用ACCEPT ... ON EXCEPTION

阿拉

   identification division.
   program-id. sample.

   data division.
   working-storage section.
   01 the-fields.
      05 field-one         pic x(8).
      05 field-two         pic x(8).
      05 field-three       pic x(8).
      05 field-four        pic x(8).

  *> ***************************************************************
   procedure division.

   accept field-one end-accept
   display field-one end-display

   accept field-two end-accept
   display field-two end-display

   accept field-three
       on exception
           display "no field three entered" end-display
       not on exception
          display field-three end-display
   end-accept

   accept field-four
       on exception
           display "no field four entered" end-display
       not on exception
           display field-four end-display
   end-accept

   goback.
   end program sample.

所以有四行输入的运行看起来像

./sample <fourdatums.txt
one
two
three
four

只有三个

./sample <threedatums.txt
one
two
three
no field four entered

答案 2 :(得分:0)

由于funexit是在命令替换创建的子shell中执行的,因此您需要在here文档之外检查其退出状态,以确定父shell是否应该退出。

#!/bin/bash
funexit () {
  echo "calling funexit"
  exit 1
}

output=$(funexit) || exit

/caplus/pub/test123<<:EOD:
1
g
$output
Y
:EOD:

答案 3 :(得分:0)

将函数的输出分配给heredoc之外的变量并检查那里的失败:

#!/bin/bash
funexit ()
{
    exit 1
}

if ! funexitvalue=$(funexit) ; then
    echo "Failure!"
    exit 1
fi


/caplus/pub/test123<<:EOD:
1
g
$funexitvalue
Y
:EOD:

如果funexit未成功退出,这将阻止COBOL程序运行。

<强>解释

bash中的命令替换($(...))总是“工作”,因为替换被命令的输出替换。即使命令退出并出现错误:

$ echo "$(echo foobar; exit 1)"
foobar
$ echo $?
0

如您所见,即使替换中的命令失败,第一个echo也会成功退出。命令替换的返回码不会以任何方式影响实际命令。

相反:

$ a="$(echo foobar; exit 1)"
$ echo $?
1
$ echo $a
foobar

此处命令替换的返回代码不会被任何其他命令遮蔽,因此您可以实际检查它是否成功返回。无论如何,将输出分配给a仍然是成功的。


注意:如果您希望COBOL程序运行到发生错误输入的位置,那么heredocs 的方式,因为它们在它们是偶数之前被完全评估传递给该计划。所以对于heredocs来说这是一个全有或全无的交易。

答案 4 :(得分:0)

heredoc将由shell解析并作为输入完整传递,并且您的方法不会起作用。但是,你当然可以打破输入:

{ cat << EOF
This text will always be entered to the test123 executable;
EOF
funexit  # exit or return, as needed
cat << EOF
If funexit returned, this will go to test123.
If funexit exited, it will not
EOF
} | caplus/pub/test123