linux 管道输出到bash函数

vfh0ocws  于 2023-11-17  发布在  Linux
关注(0)|答案(9)|浏览(169)

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

jc_hms(){
  printf "$1"
}

字符串
我想用这种方式。

var=`echo "teststring" | jc_hms`


当然,我使用了多余的函数echo和printf来简化这个问题,但是你明白了。现在我得到了一个“not found”错误,我想这意味着我的参数分隔符是错误的(“$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`


就像这样。

ibps3vxo

ibps3vxo1#

为了回答你的实际问题,当一个shell函数在管道的接收端时,标准输入被函数中的 * 所有 * 命令继承,但是只有真正从标准输入读取的命令才会消耗任何数据。对于一个接一个运行的命令,后面的命令只能看到前面的命令没有消耗的数据。当两个命令并行运行时,哪些命令看到哪些数据取决于OS如何调度命令。
由于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读取标准输入,请告诉我们。

zsohkypk

zsohkypk2#

你不能像这样直接把东西导入bash函数,但是你可以使用read来拉取它:

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

字符串
应该是你想要的

djmepvbi

djmepvbi3#

1)我知道这是一个相当古老的职位
2)我喜欢这里的大部分答案
然而,我发现这篇文章是因为我需要类似的东西。虽然每个人都同意stdin是需要使用的,但这里缺少的答案是/dev/stdin文件的实际用法。
使用read内置函数会强制此函数与管道输入一起使用,因此不能再以典型的方式使用它。我认为利用/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


我希望这可以帮助某人。
黑客愉快!

ui7jx7zq

ui7jx7zq4#

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

jc_hms() {
    cat
}

字符串
尽管到目前为止所有的答案都忽略了这不是OP想要的事实(他说功能被简化了)

disho6za

disho6za5#

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

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

字符串

x6492ojm

x6492ojm6#

唔......

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。

o2gm4chl

o2gm4chl7#

建议的解决方案要求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不适合我。
您可能必须使用不同的超时值。值太小可能会导致错误,而超时值太大则会延迟脚本。

kokeuurv

kokeuurv8#

似乎没有什么工作,但有工作周围
提到work around xargs ref function

$ FUNCS=$(functions hi); seq 3 | xargs -I{} zsh -c "eval $FUNCS; hi {}"

字符串
那么这也不起作用,因为你的函数可以引用另一个函数。所以我最终写了一些接受管道输入的函数,像这样:

somefunc() {
    while read -r data; do
        printf "%s" "$data"
    done
}

3duebb1j

3duebb1j9#

我知道这是一个老职位,但它是第一个结果给我带来的搜索引擎时,我正在寻找正确的方法来做。
我喜欢这种方式,因为它可以涵盖所有情况:
(a)在函数中通过参数接受数据,如$1
(b)通过管道接受数据
(c)如果/dev/stdin没有打开,避免挂起-管道中没有数据或没有给出参数

function somefunc() {
if test -n "$1"; then
   dt="$1"
   #Read from positional argument $1;
elif test ! -t 0; then
   dt="$(</dev/stdin)"
   #Read from stdin if file descriptor /dev/stdin is open
else
   echo "No standard input."
fi
}

字符串
来源:https://www.baeldung.com/linux/pipe-output-to-function

相关问题