管道输出到bash功能

时间:2012-07-12 14:42:22

标签: linux bash pipe

我在bash脚本中有一个简单的函数,我想将stdout作为输入来管道。

jc_hms(){
  printf "$1"
}

我想以这种方式使用它。

var=`echo "teststring" | jc_hms`

当然我使用冗余函数echo和printf来简化问题,但是你明白了。现在我得到一个“未找到”错误,我认为这意味着我的参数分隔错误(“$ 1”部分)。有什么建议吗?

最初jc_hms函数的用法如下:

echo `jc_hms "teststring"` > //dev/tts/0

但是我想先将结果存储在变量中,然后再将其发送到串口进行进一步处理。

编辑: 所以要澄清一下,我不是想把东西打印到串口,我想接口我的bash函数应该是“|”管道特征,我想知道这是否可能。

编辑:好的,这是完整的功能。

jc_hms(){
  hr=$(($1 / 3600))
  min=$(($1 / 60))
  sec=$(($1 % 60))

  printf "$hs:%02d:%02d" $min $sec
}

我正在使用该函数来形成一行代码

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

其中$ songtime是一个表示为“playtime totaltime”的字符串,以空格分隔。

我希望我可以在一行中执行此操作,并在awk之后将其管道

printstring=`echo $songtime | awk '{print S1 }' | jc_hms`
像这样。

8 个答案:

答案 0 :(得分:57)

要回答您的实际问题,当shell函数位于管道的接收端时,标准输入将由函数内部执行的第一个命令读取。由于printf是函数中的第一个也是唯一一个命令,因此忽略标准输入。有几种方法,包括使用read内置函数将标准输入读入变量,该变量可以传递给printf

jc_hms () {
    read foo
    hr=$(($foo / 3600))
    min=$(($foo / 60))
    sec=$(($foo % 60))
    printf "%d:%02d:%02d" "$hr" "$min" "$sec"
}

但是,由于您对管道的需求似乎取决于您认为需要使用awk,所以让我建议以下替代方案:

printstring=$( jc_hms $songtime )

由于songtime由空格分隔的数字组成,因此shell会对songtime的值执行分词,而jc_hms会看到两个单独的参数。这不需要改变jc_hms的定义,也不需要通过标准输入将任何东西输入其中。

如果您仍然有jc_hms阅读标准输入的其他原因,请告诉我们。

答案 1 :(得分:45)

你无法将内容直接传递给bash函数,但是你可以使用read来代替它:

jc_hms(){
  while read data; do
      printf "%s" "$data"
  done
}

应该是你想要的

答案 2 :(得分:31)

1)我知道这是一篇非常古老的帖子

2)我喜欢这里的大部分答案

然而,我发现这篇文章是因为我需要类似的东西。虽然每个人都同意stdin是需要使用的东西,但这里缺少的答案是/ dev / stdin文件的实际用法。

使用read builtin强制此函数与管道输入一起使用,因此无法再以典型方式使用。我认为使用/ dev / stdin是一种解决这个问题的优秀方法,所以我想加上我的2美分来完成。

我的解决方案:

jc_hms() { 
  declare -i i=${1:-$(</dev/stdin)};
  declare hr=$(($i/3600)) min=$(($i/60%60)) sec=$(($i%60));
  printf "%02d:%02d:%02d\n" $hr $min $sec;
}

行动中:

user@hostname:pwd$ jc_hms 7800
02:10:00
user@hostname:pwd$ echo 7800 | jc_hms 
02:10:00

我希望这可以帮助别人。

快乐的黑客攻击!

答案 3 :(得分:15)

或者,你也可以用一种简单的方式来做。

jc_hms() {
    cat
}

虽然到目前为止所有的答案都忽视了这不是OP想要的事实(他说这个功能已经简化了)

答案 4 :(得分:9)

我喜欢user.friendly的答案,使用Bash内置条件取消替换语法。 这是一个轻微的调整,使他的答案更通用,例如对于具有不确定参数计数的情况:

function myfunc() {
    declare MY_INPUT=${*:-$(</dev/stdin)}
    for PARAM in $MY_INPUT; do
        # do what needs to be done on each input value
    done
}

答案 5 :(得分:1)

... Hmmmm

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

如果你还在调用awk,为什么不使用它呢?

printstring=`TZ=UTC gawk -vT=$songplaytime 'BEGIN{print strftime("%T",T)}'`

我假设你正在使用Gnu的Awk,这是最好的,也是免费的;这将在常见的Linux发行版中工作,这些发行版不一定使用最新的gawk。最新版本的gawk将允许您将UTC指定为strftime()函数的第三个参数。

答案 6 :(得分:0)

建议的解决方案要求stdinread上的内容只能有条件地调用。否则,该功能将等待控制台中的内容,并需要 Enter Ctrl + D 才能继续。

一种解决方法是将read与超时一起使用。例如read -t <seconds>

function test ()
{
  # ...
  # process any parameters
  # ...
  read -t 0.001 piped
  if [[ "${piped:-}" ]]; then
    echo $piped
  fi
}

请注意,-t 0对我不起作用。
您可能必须为超时使用其他值。 值太小可能会导致错误,并且太大的超时会延迟脚本。

答案 7 :(得分:-1)

猜你的意思:

var=$(jc_hms `echo "teststring"`)

var=$(jc_hms $(echo "teststring"))