编写一个 Shell 函数,同时接受来自管道的输入和参数
Writing a Shell Function that accepts input from a pipe and arguments simultaneously
我正在尝试编写一个我称为 logAction
的函数,专门用于 Ksh
,它从管道读取输入并在同一个函数调用中接受参数。在 Google 和类似网站上搜索 2 周以来,我一直在尝试调试它。
我尝试创建的函数的目的是简化将我开发的其他脚本的输出记录到日志文件的过程。我打算在各种情况下使用该命令,但最容易描述和说明我正在尝试的 2 个类似于以下内容:
语法示例 1:
logAction 1 "Script executed some action."
语法示例 2:
COMMAND1 | COMMAND2 | logAction 1
如您所见,我希望能够将预期的日志信息作为参数或通过管道作为标准输入传递给函数,以便捕获命令序列的输出。第三种情况是在管道输出之前添加一些文本,即
语法示例 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 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
}
最初,我没有为read
命令提供-t
参数,函数会暂停执行,直到用户输入CTRL-D
表示EOF
.但是,就我的目的而言,此功能旨在进行静默操作,不应请求用户输入。在 read
命令中添加 -t 0
参数会告诉读取命令超时 0 秒,而不是等待来自键盘的 EOF
。
这解决了某些情况下的问题;但是,read
命令在与 cat
命令一起使用时不会捕获任何输入,如下所示:
cat somefile.txt | logAction 1
cat somefile.txt | awk '{ a=a" " }END{ print a }' | logAction 1
但使用 echo
似乎有效:
echo "ab bc cd de ef fg gh" | logAction 1 "This is the output: "
我已经能够通过将超时的 0 更改为 0.1(即 read -t 0.1
)使其与 cat
一起工作,但我担心这是一个肮脏的解决方案。这似乎表明存在竞争条件,其中 read
命令在管道完成输出并关闭之前正在执行。这不是我所期望的,因为我认为管道序列中的前一个命令必须在执行后续命令之前完成执行。
有没有办法告诉 read
命令忽略来自键盘的标准输入并使用管道中前面命令的标准输出?我试图告诉它使用 FD0
(我认为是来自管道的标准输出,但它似乎也连接到键盘)和 -u 0
参数,但这似乎不是上班。
试试这个:
#!/bin/ksh
function log
{
ARG1=
ARG2=
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>
我正在尝试编写一个我称为 logAction
的函数,专门用于 Ksh
,它从管道读取输入并在同一个函数调用中接受参数。在 Google 和类似网站上搜索 2 周以来,我一直在尝试调试它。
我尝试创建的函数的目的是简化将我开发的其他脚本的输出记录到日志文件的过程。我打算在各种情况下使用该命令,但最容易描述和说明我正在尝试的 2 个类似于以下内容:
语法示例 1:
logAction 1 "Script executed some action."
语法示例 2:
COMMAND1 | COMMAND2 | logAction 1
如您所见,我希望能够将预期的日志信息作为参数或通过管道作为标准输入传递给函数,以便捕获命令序列的输出。第三种情况是在管道输出之前添加一些文本,即
语法示例 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 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
}
最初,我没有为read
命令提供-t
参数,函数会暂停执行,直到用户输入CTRL-D
表示EOF
.但是,就我的目的而言,此功能旨在进行静默操作,不应请求用户输入。在 read
命令中添加 -t 0
参数会告诉读取命令超时 0 秒,而不是等待来自键盘的 EOF
。
这解决了某些情况下的问题;但是,read
命令在与 cat
命令一起使用时不会捕获任何输入,如下所示:
cat somefile.txt | logAction 1
cat somefile.txt | awk '{ a=a" " }END{ print a }' | logAction 1
但使用 echo
似乎有效:
echo "ab bc cd de ef fg gh" | logAction 1 "This is the output: "
我已经能够通过将超时的 0 更改为 0.1(即 read -t 0.1
)使其与 cat
一起工作,但我担心这是一个肮脏的解决方案。这似乎表明存在竞争条件,其中 read
命令在管道完成输出并关闭之前正在执行。这不是我所期望的,因为我认为管道序列中的前一个命令必须在执行后续命令之前完成执行。
有没有办法告诉 read
命令忽略来自键盘的标准输入并使用管道中前面命令的标准输出?我试图告诉它使用 FD0
(我认为是来自管道的标准输出,但它似乎也连接到键盘)和 -u 0
参数,但这似乎不是上班。
试试这个:
#!/bin/ksh
function log
{
ARG1=
ARG2=
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>