使用 xargs 调用 shell 函数

     2023-02-21     56

关键词:

【中文标题】使用 xargs 调用 shell 函数【英文标题】:Calling shell functions with xargs 【发布时间】:2012-06-15 17:37:20 【问题描述】:

我正在尝试使用 xargs 来并行调用更复杂的函数。

#!/bin/bash
echo_var()
    echo $1
    return 0

seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var  
exit 0

这会返回错误

xargs: echo_var: No such file or directory

欢迎任何关于如何使用 xargs 来完成此任务的想法或任何其他解决方案。

【问题讨论】:

危险,user1148366,危险!不要使用 bash 进行并行编程——你会遇到很多问题。使用 C/C++ 和 pthread,或 Java 线程,或任何让您对自己正在做的事情进行长时间思考的东西,因为并行编程需要大量思考才能正确。 @DavidSouther 如果任务是独立的,例如将所有这些图片文件转换为 png,那么不用担心。当你有同步(而不是等待所有完成)和通信时,它就会变得混乱。 @DavidSouther - 我是一名长期的 Java 开发人员,最近一直在使用 groovy。而且我继续告诉人们:朋友不要让朋友写 bash 脚本。然而,我发现自己在看这个帖子/解决方案,因为(悲伤的脸:()我在 bash 中从事并行处理。我可以很容易地在 groovy/java 中做到这一点。糟糕! 也在unix.stackexchange.com/questions/158564/…中讨论过 【参考方案1】:

导出函数应该可以做到(未经测试):

export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I  bash -c 'echo_var "$@"' _ 

您可以使用内置的printf 而不是外部的seq

printf "n%04g\n" 1..100 | xargs -n 1 -P 10 -I  bash -c 'echo_var "$@"' _ 

另外,使用return 0exit 0 可以屏蔽前面的命令可能产生的任何错误值。此外,如果没有错误,它是默认设置,因此有些多余。

@phobic 提到 Bash 命令可以简化为

bash -c 'echo_var ""'

直接移入其中。 但是正如@Sasha 所指出的,它容易被命令注入

以下是您不应使用嵌入格式的示例:

$ echo '$(date)' | xargs -I  bash -c 'echo_var ""'
Sun Aug 18 11:56:45 CDT 2019

为什么不的另一个例子:

echo '\"; date\"' | xargs -I  bash -c 'echo_var ""'

这是使用安全格式输出的内容:

$ echo '$(date)' | xargs -I  bash -c 'echo_var "$@"' _ 
$(date)

这相当于使用parameterized SQL queries 来避免injection。

我在此处的命令替换或转义引号中使用 date,而不是 Sasha 评论中使用的 rm 命令,因为它是非破坏性的。

【讨论】:

再讨论一下:xargs 执行一个名为进程的全新实例。在这种情况下,您提供名称 echo_var,它是此脚本中的一个函数,而不是您的 PATH 中的一个进程(程序)。 Dennis 的解决方案是导出函数供 bash 子进程使用,然后分叉到子进程并在那里执行。 _\ 的意义是什么,没有它们对我不起作用 @Hashbrown:下划线 (_) 为 argv[0] ($0) 提供了一个占位符,几乎可以在其中使用任何东西。我想我添加了反斜杠分号(\;),因为它用于终止find 中的-exec 子句,但在这里没有它对我有用。事实上,如果函数使用$@ 而不是$1,那么它会将分号视为参数,所以应该省略它。 -i 参数 xargs 已被弃用。改用 -I(大写 i)。 您可以通过在带有bash -c 'echo_var ""' 的bash 的命令字符串中包含来自xargs 的参数来简化此操作。所以你最后不需要 _ 。【参考方案2】:

使用 GNU Parallel 看起来像这样:

#!/bin/bash
echo_var()
    echo $1
    return 0

export -f echo_var
seq -f "n%04g" 1 100 | parallel -P 10 echo_var  
exit 0

如果您使用版本 20170822,您甚至不必export -f,只要您运行了这个:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var  

【讨论】:

在下面得到这个错误 Ole sh: parallel_bash_environment: line 67: unexpected EOF while looking for matching '' sh:parallel_bash_environment:第 79 行:语法错误:文件意外结束 sh:为 parallel_bash_environment' /usr/local/bin/bash: parallel_bash_environment: line 67: unexpected EOF while looking for matching ''/usr/local/bin 导入函数定义时出错/bash:parallel_bash_environment:第 79 行:语法错误:文件意外结束 /usr/local/bin/bash:为 ` ... 导入函数定义时出错 你被shellaftershocked了:Shellshock并没有直接影响GNU Parallel。然而,shellshock 的解决方案确实做到了:它完全破坏了 --env 和 env_parallel 技巧。相信在git版本中已修复:git.savannah.gnu.org/cgit/parallel.git/snapshot/… 我喜欢这个答案,因为它让我发现了并行工具【参考方案3】:

这样的事情也应该起作用:

function testing()  sleep $1 ; 
echo 1..10 | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "

【讨论】:

一般来说,这会破坏 shell 特殊字符(例如|#)并忽略输入中的空格。我建议让 xargs 按原样传递它们,而不是让 bash 将输入视为代码。 echo 1..10 | xargs -n 1 -P4 bash -c "$(declare -f testing);"' testing "$@"; echo "$@";' argv0【参考方案4】:

似乎我不能制作 cmets :-(

我想知道重点是

bash -c 'echo_var "$@"' _ 
vs
bash -c 'echo_var ""'

第一个将 替换为 bash 的 arg,而第二个替换为函数的 arg。示例 1 没有扩展 $(date) 的事实只是一个副作用。

如果您不希望函数 args 扩展,请使用单引号而不是双引号。为避免嵌套混乱,请使用双引号(在另一个上扩展 args)

$ echo '$(date)' | xargs -0 -L1 -I  bash -c 'printit ""'
Fri 11 Sep 17:02:24 BST 2020

$ echo '$(date)' | xargs -0 -L1 -I  bash -c "printit ''"
$(date)

【讨论】:

【参考方案5】:

也许这是不好的做法,但如果您在 .bashrc 或其他脚本中定义函数,您可以使用 allexport 的设置包装文件或至少函数定义:

set -o allexport

function funcy_town 
  echo 'this is a function'

function func_rock 
  echo 'this is a function, but different'

function cyber_func 
  echo 'this function does important things'

function the_man_from_funcle 
  echo 'not gonna lie'

function funcle_wiggly 
  echo 'at this point I\'m doing it for the funny names'

function extreme_function 
  echo 'goodbye'


set +o allexport

【讨论】:

课时9:shell函数使用方法(代码片段)

Shell函数使用方法函数的作用:把一个功能封装起来,使用时直接调用函数名。这样写脚本的好处是使得脚本模块化,代码整体的可读性强。函数定义:函数名()命令序列或者:function函数名()命令序列函数调用... 查看详情

我可以从另一个 shell 脚本调用一个 shell 脚本的函数吗?

...hfunc1func2first.sh将调用带有一些参数的第二个shell脚本和将使用特定于该函数的一些其他参数调用fu 查看详情

xargs原理&使用(代码片段)

...xargs后面的命令  xargs默认的分隔符:空格或回车2.参数使用  想把所有.jpg文件删除,当然你可以 rm*.jpg,但是如果要递归操作所有子目录下的文件呢?  可以这样:find.-name"*.jpg"|xargsrm   这样,所有被find找到的文... 查看详情

shell中函数的定义和使用

...尽管在Shell中函数并非是必须的编程元素,但是通过使用函数,可以对程序进行更加好的组织。将一些相对独立的代码变成函数,可以提高程序的可读性和重用性。避免重复编写大量相同的代码。函数的定义在Shell中... 查看详情

如何使用shell函数修改表中一行的每个值?

】如何使用shell函数修改表中一行的每个值?【英文标题】:Howtomodifyeveryvalueofarowinatableusingshellfunction?【发布时间】:2020-06-2223:05:23【问题描述】:需要修改表中每一列中的一行。这是通过从shell调用的函数完成的。需要使用sqlpl... 查看详情

shell函数

...只需要改变函数体内的一份代码即可实现所有调用修改。使用函数的优势:1、把相同的程序段定义成函数,可以减少整个程序的代码量。2、增加程序的可读、易读性。3、可以实 查看详情

如何从 shell 脚本调用 GAP 函数?

...个交互式命令行工具,主要供从事群论相关主题的数学家使用。文档/常见问题解答关于8.1:CanIcallGAPfunctionsfromanotherprogramme?的状态通常是不可能的。但是,将GA 查看详情

基于armlinux的shell函数定义函数调用及函数返回值用法(代码片段)

...键字:函数名()函数体格式2:这是标准写法,也推荐大家使用的写法:function函数名()命令序列这样方便做到一看就懂。格式3:如果写了function关键字,也可以 查看详情

基于armlinux的shell函数定义函数调用及函数返回值用法(代码片段)

...键字:函数名()函数体格式2:这是标准写法,也推荐大家使用的写法:function函数名()命令序列这样方便做到一看就懂。格式3:如果写了function关键字,也可以 查看详情

linux常用shell函数参数

函数参数传递给函数使用的值称为函数的参数传递参数给函数:在函数名后面以空白分隔给定参数列表即可,如:testfuncarg1arg2…在函数体中当中,可使用$1,2,...调用这些参数;还可以使用2,...调用这些参数࿱... 查看详情

如果上一个命令没有返回任何内容,则不要调用 xargs [重复]

】如果上一个命令没有返回任何内容,则不要调用xargs[重复]【英文标题】:Don\'tcallxargsifthepreviouscommanddoesn\'treturnanything[duplicate]【发布时间】:2013-09-1916:51:54【问题描述】:我有以下命令检查是否添加了任何新文件并在所有这些... 查看详情

shell函数和数组

一、函数1、函数使用方法定义函数再引用函数查看系统限制所有函数:declare-F看函数定义详细内容:declare-f 函数名  删除函数:unset 函数名 2、注意事项直接写函数中调用函数直接写函数名同名函数后一个生... 查看详情

基于armlinux的shell函数定义函数调用及函数返回值用法(代码片段)

...键字:函数名()函数体格式2:这是标准写法,也推荐大家使用的写法:function函数名()命令序列这样方便做到一看就懂。格式3:如果写了function关键字,也可以省略函数名后面的小括号:function函数名命令序列说明:function是Shell... 查看详情

shell自定义函数(代码片段)

函数调用通常将函数看成是脚本中的一段代码,在使用函数前必须先定义该函数,使用时利用函数名直接调用。例:编写脚本func_script,内容如下。#!/bin/bashREPEAT=3fa()echo"Nowfafunctionisstarting..."echofb()i=0echo"Andnowthefbbebins."sleep1while[$i-l... 查看详情

xargs

变量置换,主要用于不支持管道的shell命令,如:rm、sed等。比如:删除文件- ls|xargs-irm-rf{}文件改名- ls|xargs-imv{}{}.old将命令逐个替换到{}执行命令:xargs当find产生一个文件列表时,该列表提供给另一个命令有时是很有用的.$f... 查看详情

shell函数

...量来获得函数返回值。像删除变量一样,删除函数也可以使用unset命令,不过要加上-f选项,如下所示:如果你希望直接从终端调用函数,可以将函数定义在主目录下的.profile文件,这样每次登录后,在命令提示符后面输入函数名... 查看详情

shell脚本入门06:函数与模块化(代码片段)

...模块化总结目的函数与模块化可以让相同功能的代码重复使用,这对于开发复杂项目来说是必须的,这篇文章将对相关内容做个说明。函数定义函数Shell中函数的定义方式如下:functionname()statementsreturnvaluefunction可以省... 查看详情

使用 xargs 运行多个命令

】使用xargs运行多个命令【英文标题】:Runningmultiplecommandswithxargs【发布时间】:2011-10-2023:35:22【问题描述】:cata.txt|xargs-I%echo%在上面的示例中,xargs将echo%作为命令参数。但在某些情况下,我需要多个命令来处理参数而不是一个... 查看详情