我想为ls | grep pattern -的每个匹配项运行一次Java命令。在这种情况下,我想我可以执行find pattern -exec java MyProg '{}' \;,但我对一般情况感到好奇-是否有一种简单的方式说“每行标准输入运行一次命令”? (以鱼或b为食。)

#1 楼

这就是xargs的功能。

... | xargs command


评论


不完全的。 printf“ foo bar \ nbaz bat” | xargs echo whee将产生whee foo bar baz bat。也许添加-L或-n选项?

–詹德
2011-2-17在5:17



@Jander这个问题相当笼统,所以我给出了常规工具。没错,您必须根据具体情况使用选项调整其行为。

–基思
2011-2-17在5:25

... | tr'\ n''\ 0'| xargs -0

–vrdhn
2011-2-17在11:12

例如“为问题提供正确答案的特定情况”。 :)

–mattdm
2011-2-17在18:17

如果您想了解使用xargs执行此操作的正确方法,请参见下面的答案。

– Michael Goldshteyn
15年6月30日在16:08

#2 楼

公认的答案是正确的主意,但关键是要传递xargs-n1开关,这意味着“每个命令行最多使用1个参数”:
cat file... | xargs -n1 command

于2020-08-05更新:
我也想回应用户Jander的评论中发现的建议,该建议被强烈反对尽管包含一些错误信息,但我现在将要解释。在我看来,此开关带来的弊大于利,对于cat而言,一次表示作用于一个非空行肯定是一个延伸。公平地说,-L的手册页确实阐明了xargs开关随附的功能(读作:问题)。
由于Jander在提到-L 1时可能没有急于想像的StackOverflow读者,没有提及问题快速提示,没有时间去阅读手册页等乏味的事情,而不是像福音一样接受评论和回答,我现在将说明为什么xargs是一个非常糟糕的建议,而没有仔细了解它带来的所有行李
为了演示我对-L的鄙视,让我展示一个名为-L的简单输入文件,其中包含以下文本:
<file xargs -n1 command

包含数字-L的字符带有空格字符(在前面的代码中,在数字-L之后显示为Unicode mynumbers.txt字形,以防您的浏览器字体不具有此Unicode charac的视觉表示ter),使用2的命令,例如:
1
2␠
3

...,将产生以下(也许令人惊讶)输出:
<mynumbers.txt xargs -L1 echo

这是由于以下事实引起的:SYMBOL FOR SPACE开关指示2将后续行附加到以空格结尾的行,这种行为可能仅在行没有适当地修剪尾随空格的奇数时刻才影响结果输出-定时炸弹错误等待正确的输入文件显示自己。
另一方面,使用xargs -L1-L开关而不是xargs的同一命令将产生更可接受的输出:也许更令人惊讶的是,与-n 1不同的xargs开关强制-L 1-L选项生效。如果遇到命令行认为对于运行它的环境来说太长的命令行,则会导致-n进程终止。
包含许多行并连续带有尾随空格的输入文件可能会导致-x终止中途运行如果所有这些都串联到一个超行中,则超过xargs的定义(对于命令行而言太长了)-大小由xargs根据运行平台所指定的最大长度确定,并根据看似任意的常数进一步偏移(请记住微积分中那些令人讨厌的不定积分,并在一个或两个测验/测试中丢失点,因为您忘记了对积分的求解后忘记写xargs吗?)如手册页中所述。
xargs一方面,xargs的值只是将这些行切成(希望的)一口大小的单行块,并与它们一起执行提供给+ C的命令
关于xargs手册页的附加说明:我不知道为什么在整个-n手册页中都使用了模棱两可和非标准的单词空白定义更好,模棱两可的选项,例如:

空格,如果空格表示一个或多个ASCII空格字符
除换行符以外的空白(如果这实际上是空格的意思)
该集合中的一个或多个不可打印字符: {空格,水平制表符}(如果这导致使用空白作为看似很好的说明性选择)


评论


同样有趣的是,如果stdin为空,则xargs不能运行:--no-run-if-empty -r:如果标准输入不包含任何非空格,请不要运行该命令。通常,即使没有输入,命令也会运行一次。此选项是GNU扩展。

–罗南长袍
2015年10月24日19:58



您如何访问line inside命令?

– B T
16-4-14的1:21

这是xargs的正确用法。如果不使用-n1,它仅适用于将参数列表视为多次调用的命令,而并非全部。

– masterxilo
18年3月15日在9:43

printf“ foo bar \ nbaz bat” | xargs -n1 echo whee按单词而不是按行拆分

– Gismo Ranas
18-10-24在8:32

@B T,我认为您对xargs扮演的角色有基本的误解。考虑(并亲自尝试)以下命令:头-n 1 | xargs -n 1回显。从逻辑上讲,它只是说:echo'y'。你问那是哪里人?这是yes输出的第一行。当与-n 1开关一起使用时,您所说的访问该行是xargs传递给命令的唯一参数。换句话说,对于输入的每一行,命令都以该行作为参数传入的方式执行。

– Michael Goldshteyn
20年8月5日在4:13



#3 楼

在Bash或任何其他Bourne样式的外壳程序(ash,ksh,zsh等)中: ,您不想要那样)。因此,您可以执行以下任一操作:

while read -r line; do command "$line"; done


评论


当我尝试tail -f syslog | grep -e something -e somethingelse |边读边;做回声$ line;完成它没有用。它使用管道传递到while循环中的文件,仅使用尾部-f,仅使用grep,但不适用于两个管道。给grep提供--line-buffered选项可以使其工作

–user16468
2012年10月10日20:39



当每行都需要发送到stdin时,此方法也适用:而读-r行;回显“ $ line” |命令;完成

–丹
18/09/10在9:27



#4 楼

我同意Keith的观点,xargs是最通用的工具。

我通常使用3步方法。您想使用的东西
使用awk准备行,以便它获得正确的语法
,然后让xargs也许在bash的帮助下执行它。

和更快的方法,但是这种方法几乎总是可行。 ,
然后awk用一个要执行的命令和一些参数准备一个漂亮的字符串,并且$ 1是管道的第一列输入。 。

有点矫kill过正,但是此食谱非常灵活,因此在很多地方对我都有帮助。

还请注意,您还可以执行xargs -0 -n1 bash -c(只需添加Michael Goldshteyn建议的-n1标志)即可在输出的每一行上执行命令。

评论


注意,xargs -0使用空字节作为记录分隔符,因此您的awk打印语句应为printf(“ MyJavaProg --args \”%s \“ \ 0”,$ 1)

–格伦·杰克曼
2011-02-17 14:30



@glenn:缺少空字符,将更新答案

–约翰
2011-2-18在12:43

@Johan没什么大不了的,但是如果您使用的是awk,则可以进行模式匹配并跳过grep,例如ls | awk'/ xls / {打印...

–埃里克·雷诺夫(Eric Renouf)
16年5月31日在15:19

#5 楼

GNU Parallel专为此类任务而设计。最简单的用法是:

cat stuff | grep pattern | parallel java MyProg


观看介绍视频以了解更多信息:http://www.youtube.com/watch?v=OpaiGYxkSuQ

评论


这里不需要猫,因为grep可以直接读取文件

–埃里克·雷诺夫(Eric Renouf)
16年5月31日在15:20

@EricRenouf oletange.blogspot.dk/2013/10/useless-use-of-cat.html

–奥雷·丹吉(Ole Tange)
16年5月31日在20:29

感谢您提供的链接,我不一定同意它更容易阅读,但是很高兴知道它被考虑了。我现在只是稍微怀疑一下,该链接实际上并没有在这里应用,因为替代方法并不是真正的<东西grep模式,而是完全不需要重定向或cat的grep模式东西。不过,这并不会从根本上改变您的观点,如果您认为始终在以cat开头的管道中使用东西会更清晰,那么将为您供电

–埃里克·雷诺夫(Eric Renouf)
16年1月1日,0:32

#6 楼

如果需要控制将输入参数确切地插入命令行的位置,或者需要重复几次,则可以使用xargs -I{}

示例#1

another_folder中创建一个空文件夹结构,以反映当前目录中的子文件夹:



     ls -1d ./*/ | xargs -I{} mkdir another_folder/{}
 


示例2

对来自stdin的文件列表应用操作,在这种情况下,通过附加.html扩展名来复制每个.bak文件:

     find . -iname "*.html" | xargs -I{} cp {} {}.bak
 


从Mac OS / BSD的xargs手册页:

  -I replstr
         Execute utility for each input line, replacing one or more occurrences of
         replstr in up to replacements (or 5 if no -R flag is specified) arguments
         to utility with the entire line of input.  The resulting arguments, after
         replacement is done, will not be allowed to grow beyond 255 bytes; this is
         implemented by concatenating as much of the argument containing replstr as
         possible, to the constructed arguments to utility, up to 255 bytes.  The
         255 byte limit does not apply to arguments to utility which do not contain
         replstr, and furthermore, no replacement will be done on utility itself.
         Implies -x.
 


Linux xargs手册页:

    -I replace-str
          Replace  occurrences of replace-str in the initial-
          arguments with names read from standard input.  Al‐
          so,  unquoted  blanks do not terminate input items;
          instead the separator  is  the  newline  character.
          Implies -x and -L 1.
 


#7 楼

另外,while read在鱼壳中循环(考虑到您使用的是鱼牌,我假设您要鱼壳)。

/>

read不带-r参数,并且不解释您的反斜杠,从而使最常见的用例变得容易。与bash不同,fish不会用空格来分隔变量。将其替换为实际命令。


评论


同时不需要与do&done配对而不是结束吗?

–aff
18年11月19日在7:55

@aff这是关于鱼壳的,它具有不同的语法。

– Konrad Borowski
18-11-19在14:29

啊,这就是鱼的意思。

–aff
18年11月20日在6:33

#8 楼

在这里,您可以立即使用复制粘贴:

cat list.txt | xargs -I{} command parameter {} parameter


列表中的项目将放在{}所在的位置,其余的命令和参数将被使用原样

#9 楼

在处理可能未经过消毒的输入时,我希望在运行它之前逐行查看整个任务的“拼写”以进行视觉检查(尤其是在破坏性工作,例如清理人们的邮箱时)。我要做的是生成一个参数列表(即用户名),以每行一个记录的方式将其馈送到文件中,如下所示:
我在vim中打开列表,并用搜索和替换表达式进行处理,直到获得需要执行的完整命令列表,例如:

johndoe  
jamessmith  
janebrown  


此如果您的正则表达式不完整,您将看到在哪个命令中有潜在的问题(即/bin/rm -fr johnnyo connor)。这样,您可以撤消正则表达式,然后使用更可靠的版本再次尝试。名字修饰对此是臭名昭著的,因为很难照顾到凡高,奥康纳斯,圣克莱尔,史密斯-韦森这样的边缘案件。

具有set hlsearch,因为它将突出显示所有匹配项,因此您可以轻松发现是否匹配项,或者以意外方式进行匹配。

一旦您的正则表达式很完美,它将捕获所有可能的情况测试/考虑,然后通常将其转换为sed表达式,以便可以完全自动化以进行另一次运行。我强烈建议在执行命令之前在屏幕上回显该命令(或者更好的是,一条日志),因此,如果出错,则可以确切知道是哪个命令导致该命令失败。然后,您可以返回到原始正则表达式并再次进行调整。

#10 楼

如果程序忽略管道,但接受文件作为参数,则可以将其指向特殊文件/dev/stdin。我不熟悉Java,但是这里有一个示例对于bash:

$ echo $'pwd \n cd / \n pwd' |bash /dev/stdin
/home/rolf
/


$是bash将\n转换为换行符所必需的。我不知道为什么。

#11 楼

我更喜欢-允许多行命令并清除代码

find -type f -name filenam-pattern* | while read -r F
do
  echo $F
  cat $F | grep 'some text'
done



#12 楼

如其他答案所示,这可以通过xargs来实现。我们需要在问题的“每行一次”部分中区分两个细节:


一次:使用-n 1,这可以确保为每个参数精确地调用一次命令。但是,默认情况下,xargs假定参数是用空格分隔的-一旦文件包含空格,该参数就会中断。
每行:使用-d '\n'或使用tr '\n' '-0'预处理输入并使用tr。这样可使命令对输入中的空格具有鲁棒性。

最后的命令行将变为:

.... | xargs -n 1 -d '\n' <command>


或(带有grep

.... | tr '\n' 'q4312078q' | xargs -n 1 -0 <command>


如果您的命令可以一次处理多个参数(例如sed-n 1),则可以省略q4312079q来加快操作速度。