管道输出到bash功能

jli*_*u83 64 linux bash pipe

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

jc_hms(){
  printf "$1"
}
Run Code Online (Sandbox Code Playgroud)

我想以这种方式使用它.

var=`echo "teststring" | jc_hms`
Run Code Online (Sandbox Code Playgroud)

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

最初jc_hms函数的使用方式如下:

echo `jc_hms "teststring"` > //dev/tts/0
Run Code Online (Sandbox Code Playgroud)

但是我想先将结果存储在一个变量中,然后再将其发送到串口.

编辑:所以澄清一下,我不是想把东西打印到串口,我想接口我的bash函数应该是"|" 管道人物,我想知道这是否可行.

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

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

  printf "$hs:%02d:%02d" $min $sec
}
Run Code Online (Sandbox Code Playgroud)

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

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring
Run Code Online (Sandbox Code Playgroud)

其中$ songtime是一个以空格分隔的"playtime totaltime"表示的字符串.

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

printstring=`echo $songtime | awk '{print S1 }' | jc_hms`
Run Code Online (Sandbox Code Playgroud)

像这样.

che*_*ner 60

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

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

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

printstring=$( jc_hms $songtime )
Run Code Online (Sandbox Code Playgroud)

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

如果您仍有其他理由jc_hms阅读标准输入,请告知我们.

  • `echo` 从未完全标准化,因为已经存在太多不同(在某些情况下,相互矛盾)的实现。(例如,POSIX 标准是让 `echo` 处理像 `\t` 和 `\n` 这样的序列,`bash` 的实现不会*这样做,除非你使用非标准选项 `-e` .)' `printf` 更便携。 (3认同)

moo*_*pet 46

你不能直接将东西管道传递给这样的bash函数,但你可以用read它来代替它:

jc_hms(){
  while read data; do
      printf "%s" "$data"
  done
}
Run Code Online (Sandbox Code Playgroud)

应该是你想要的

  • 它应该是`printf"%s""$ data"`否则`$ data`将作为格式字符串重新编号. (4认同)

use*_*dly 33

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;
}
Run Code Online (Sandbox Code Playgroud)

在行动:

user@hostname:pwd$ jc_hms 7800
02:10:00
user@hostname:pwd$ echo 7800 | jc_hms 
02:10:00
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助别人.

快乐的黑客!

  • 绝对的黄金,谢谢!在安装了 bash 4.4 的 MacOS 上,我无法使用 `declare -i`,但只是完成了我的作业:`i=${1:-$(&lt;/dev/stdin)};` (4认同)
  • 非常有帮助 - 我正是有这个需求,能够在函数中处理 args 或 stdin。 (2认同)

Jo *_* So 15

或者,您也可以通过简单的方式完成.

jc_hms() {
    cat
}
Run Code Online (Sandbox Code Playgroud)

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


Der*_*ley 11

我喜欢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
}
Run Code Online (Sandbox Code Playgroud)