将输出管道传输到 bash 函数

2024-10-29 08:35:00
admin
原创
44
摘要:问题描述:我在 bash 脚本中有一个简单函数,我想将 stdout 作为输入传送给它。jc_hms(){ printf "$1" } 我想以这种方式使用它。var=`echo "teststring" | jc_hms` 当然,我使...

问题描述:

我在 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`

就像这样。


解决方案 1:

回答您的实际问题,当 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读取标准输入,请告知我们。

解决方案 2:

您不能将内容直接通过管道传输到这样的 bash 函数,但是您可以使用它read来将其拉入:

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

应该是你想要的

解决方案 3:

1)我知道这是一篇很老的文章

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

但是,我找到了这篇文章,因为我需要一些类似的东西。虽然每个人都同意需要使用 stdin,但这里的答案缺少的是 /dev/stdin 文件的实际用途。

使用 read 内置命令会强制此函数与管道输入一起使用,因此它不再能以典型方式使用。我认为利用 /dev/stdin 是解决这个问题的更好方法,因此我想补充一些我的看法以保证完整性。

我的解决方案:

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

实际操作:

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

我希望这可以帮助到别人。

快乐黑客!

解决方案 4:

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

jc_hms() {
    cat
}

尽管到目前为止所有的答案都忽略了这不是 OP 想要的事实(他表示该功能已经简化)

解决方案 5:

我喜欢 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
}

解决方案 6:

嗯嗯……

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() 函数的第三个参数。

解决方案 7:

建议的解决方案要求内容stdinread仅被有条件地调用。否则,该函数将等待来自控制台的内容,并要求EnterCtrl+D才能继续。

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

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

注意,-t 0对我来说没用。

您可能必须使用不同的超时值。值太小可能会导致错误,而超时值太大会延迟脚本。

解决方案 8:

似乎没有什么效果,但有解决办法

提到了解决 xargs ref 函数的问题

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

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

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

解决方案 9:

我知道这是一篇旧帖子,但当我寻找正确的方法时,这是搜索引擎给我带来的第一个结果。

我更喜欢这种方式,因为它可以涵盖所有情况:

(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

解决方案 10:

我修改了“Der Schley”的答案https://stackoverflow.com/a/36432966/21633953

f_myfunc() {
  local data=("${@:-$(</dev/stdin)}")
  for parm in "${data[@]}" ; do
    # do what needs to be done on each input value
  done
}
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用