编写Shell函数,同时接受来自管道和参数的输入

时间:2015-12-28 17:23:53

标签: linux function pipe stdin ksh

我试图编写一个我专门为logAction调用Ksh的函数,该函数从管道读取输入并接受同一函数调用中的参数。我已经尝试在Google和这样的网站上进行为期两周的调试。

我尝试创建的函数的目的是简化将输出记录到我已经开发的其他脚本的日志文件的过程。我打算在各种情况下使用该命令,但最简单的描述和说明我尝试的内容类似于以下内容:

语法示例1:

logAction 1 "Script executed some action."

语法示例2:

COMMAND1 | COMMAND2 | logAction 1

如您所见,我希望能够通过管道将预期的日志信息作为参数或stdinput传递给函数,以捕获命令序列的输出。第三种情况是在管道输出之前添加一些文本,即

语法示例3:

COMMAND1 | COMMAND2 | logAction 1 "This is the output:  "

下面的输出说明了使用示例3中语法的结果:

[2015/12/28 10:20:32] This is the output:  <Output from COMMAND1 | COMMAND 2>

这是我尝试创建的功能的基本框架。

function logAction {
  while read -t 0 -u 0 stdinput
  do
    echo "StdInput:'$stdinput'"
    pipedinput=$stdinput
  done
  pipedinput=${pipedinput:-}

  case $1 in
    1)  #Output text only to log file
        output=$(echo "$pretag ${@:2} $pipedinput")
        echo $output >> $LOG
    2)  #Output text to screen and log file
        output=$(echo "$pretag ${@:2} $pipedinput")
        echo $output
        echo $output >> $LOG
    3)  
        ....
  esac
  unset pipedinput
}

最初,我没有向-t命令提供read参数,该函数会暂停执行,直到用户输入CTRL-D来指示EOF 。但是,就我的目的而言,此函数旨在进行静默操作,不应请求用户输入。使用-t 0命令添加read参数告诉read命令以0秒超时,而不是等待键盘上的EOF

这解决了某些情况下的问题;但是,当read命令与cat命令一起使用时,cat somefile.txt | logAction 1 cat somefile.txt | awk '{ a=a" "$1 }END{ print a }' | logAction 1 命令不会捕获任何输入:

echo

然而,使用echo "ab bc cd de ef fg gh" | logAction 1 "This is the output: " 似乎有效:

cat

我已经能够通过将超时的0更改为0.1(即read -t 0.1)来使其与read一起使用,但我担心这是一个肮脏的解决方案。这似乎表明存在竞争条件,其中在管道完成输出并关闭之前执行read命令。这不是我的预期,因为我认为管道序列中的前一个命令必须在执行后续命令之前完成执行。

有没有办法告诉FD0命令忽略键盘中的stdin并使用管道中前一个命令的stdout?我试图告诉它使用-u 0(我认为它是来自管道的stdout,但它似乎也连接到键盘)与{{1}}参数,但是没有&#39;似乎工作。

1 个答案:

答案 0 :(得分:2)

试试这个:

#!/bin/ksh

function log 
{
    ARG1=$1
    ARG2=$2

    if [ ! -t 0 ] 
    then
        INPUT=$(cat)
    else
        INPUT=""
    fi  

    echo "<datetime>" ${ARG2}${INPUT}
}

log 1 "Script executed some action."

echo "<data from pipe>" | log 2 "this is the output: "

echo "<data from pipe>" | cat | log 2 "this is the output: "

输出:

<datetime> Script executed some action.
<datetime> this is the output: <data from pipe>
<datetime> this is the output: <data from pipe>