具有多个参数的 xargs

发布于 2024-09-24 15:34:13 字数 528 浏览 0 评论 0原文

我有一个源输入,input.txt

a.txt
b.txt
c.txt

我想将这些输入输入到程序中,如下所示:

my-program --file=a.txt --file=b.txt --file=c.txt

所以我尝试使用xargs,但没有运气。

cat input.txt | xargs -i echo "my-program --file"{}

它给出了

my-program --file=a.txt
my-program --file=b.txt
my-program --file=c.txt

但我想要

my-program --file=a.txt --file=b.txt --file=c.txt

任何想法吗?

I have a source input, input.txt

a.txt
b.txt
c.txt

I want to feed these input into a program as the following:

my-program --file=a.txt --file=b.txt --file=c.txt

So I try to use xargs, but with no luck.

cat input.txt | xargs -i echo "my-program --file"{}

It gives

my-program --file=a.txt
my-program --file=b.txt
my-program --file=c.txt

But I want

my-program --file=a.txt --file=b.txt --file=c.txt

Any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

格子衫的從容 2024-10-01 15:34:13

不要听他们所有人的。 :) 看一下这个例子:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2'

输出将是:

this is first:argument1 second:argument2 third:argument3

Don't listen to all of them. :) Just look at this example:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2'

Output will be:

this is first:argument1 second:argument2 third:argument3
任性一次 2024-10-01 15:34:13

到目前为止给出的解决方案都没有正确处理包含空格的文件名。如果文件名包含 ' 或 ",有些甚至会失败。如果您的输入文件是由用户生成的,您应该为令人惊讶的文件名做好准备。

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -N 3 my-program --file={1} --file={2} --file={3}

rel="noreferrer" >

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -X -N 3 my-program --file={}

GNU Parallel 可以很好地 程序接受命令行中容纳的尽可能多的参数:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo d1.txt; echo e1.txt; echo f1.txt;) |
parallel -X my-program --file={}

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

None of the solutions given so far deals correctly with file names containing space. Some even fail if the file names contain ' or ". If your input files are generated by users, you should be prepared for surprising file names.

GNU Parallel deals nicely with these file names and gives you (at least) 3 different solutions. If your program takes 3 and only 3 arguments then this will work:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -N 3 my-program --file={1} --file={2} --file={3}

Or:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -X -N 3 my-program --file={}

If, however, your program takes as many arguments as will fit on the command line:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo d1.txt; echo e1.txt; echo f1.txt;) |
parallel -X my-program --file={}

Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ

北城挽邺 2024-10-01 15:34:13

怎么样:

echo 
a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="$1" --file="$2" --file="$3"
' argv0

How about:

echo 
a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="$1" --file="$2" --file="$3"
' argv0
我的影子我的梦 2024-10-01 15:34:13

如果您使用两个 xargs 调用,那就更简单了:第一个将每一行转换为 --file=...,第二个实际执行 xargs 操作 ->

$ cat input.txt | xargs -I@ echo --file=@ | xargs echo my-program
my-program --file=a.txt --file=b.txt --file=c.txt

It's simpler if you use two xargs invocations: 1st to transform each line into --file=..., 2nd to actually do the xargs thing ->

$ cat input.txt | xargs -I@ echo --file=@ | xargs echo my-program
my-program --file=a.txt --file=b.txt --file=c.txt
初熏 2024-10-01 15:34:13

您可以使用 sed 在每行添加 --file= 前缀,然后调用 xargs

sed -e 's/^/--file=/' input.txt | xargs my-program

You can use sed to prefix --file= to each line and then call xargs:

sed -e 's/^/--file=/' input.txt | xargs my-program
秋心╮凉 2024-10-01 15:34:13

这是一个使用 sed 处理三个参数的解决方案,但受到限制,因为它对每个参数应用相同的转换:

cat input.txt | sed 's/^/--file=/g' | xargs -n3 my-program

这是一个适用于两个参数的方法,但允许更大的灵活性:

cat input.txt | xargs -n 2 | xargs -I{} sh -c 'V="{}"; my-program -file=${V% *} -file=${V#* }'

Here is a solution using sed for three arguments, but is limited in that it applies the same transform to each argument:

cat input.txt | sed 's/^/--file=/g' | xargs -n3 my-program

Here's a method that will work for two args, but allows more flexibility:

cat input.txt | xargs -n 2 | xargs -I{} sh -c 'V="{}"; my-program -file=${V% *} -file=${V#* }'
裸钻 2024-10-01 15:34:13

我偶然发现了一个类似的问题,并找到了一个我认为比迄今为止提出的解决方案更好、更干净的解决方案。

我结束时的 xargs 语法是(对于您的示例):

xargs -I X echo --file=X

完整的命令行是:

my-program $(cat input.txt | xargs -I X echo --file=X)

它将像

my-program --file=a.txt --file=b.txt --file=c.txt

完成一样工作(提供 input.txt包含示例中的数据)。


实际上,就我而言,我需要首先找到文件,并且还需要对它们进行排序,以便我的命令行如下所示:

my-program $(find base/path -name "some*pattern" -print0 | sort -z | xargs -0 -I X echo --files=X)

一些可能不清楚的细节(它们不适合我):

  • some*pattern必须加引号,否则 shell 会在传递给 find 之前对其进行扩展。
  • -print0,然后是 -z,最后是 -0 使用空分隔来确保正确处理带有空格或其他连线名称的文件。

但请注意,我还没有对其进行深入测试。尽管它似乎正在发挥作用。

I stumbled on a similar problem and found a solution which I think is nicer and cleaner than those presented so far.

The syntax for xargs that I have ended with would be (for your example):

xargs -I X echo --file=X

with a full command line being:

my-program $(cat input.txt | xargs -I X echo --file=X)

which will work as if

my-program --file=a.txt --file=b.txt --file=c.txt

was done (providing input.txt contains data from your example).


Actually, in my case I needed to first find the files and also needed them sorted so my command line looks like this:

my-program $(find base/path -name "some*pattern" -print0 | sort -z | xargs -0 -I X echo --files=X)

Few details that might not be clear (they were not for me):

  • some*pattern must be quoted since otherwise shell would expand it before passing to find.
  • -print0, then -z and finally -0 use null-separation to ensure proper handling of files with spaces or other wired names.

Note however that I didn't test it deeply yet. Though it seems to be working.

兔姬 2024-10-01 15:34:13

这是因为 echo 打印换行符。尝试类似的东西

echo my-program `xargs --arg-file input.txt -i echo -n " --file "{}`

It's because echo prints a newline. Try something like

echo my-program `xargs --arg-file input.txt -i echo -n " --file "{}`
魔法少女 2024-10-01 15:34:13

xargs 不是这样工作的。尝试:

  myprogram $(sed -e 's/^/--file=/' input.txt)

xargs doesn't work that way. Try:

  myprogram $(sed -e 's/^/--file=/' input.txt)
神爱温柔 2024-10-01 15:34:13

我正在寻找针对这个确切问题的解决方案,并得出了在中间编写脚本的结论。

要转换下一个示例的标准输出,请使用 -n '\n' 分隔符

示例:

 user@mybox:~$ echo "file1.txt file2.txt" | xargs -n1 ScriptInTheMiddle.sh

 inside the ScriptInTheMidle.sh:
 !#/bin/bash
 var1=`echo $1 | cut -d ' ' -f1 `
 var2=`echo $1 | cut -d ' ' -f2 `
 myprogram  "--file1="$var1 "--file2="$var2 

要使此解决方案正常工作,您需要在这些参数 file1.txt 和 file2.txt 之间有一个空格,或者您选择的任何分隔符,再一个事情,在脚本中确保您检查 -f1 和 -f2,因为它们的意思是“取第一个单词并取第二个单词”,具体取决于找到的第一个分隔符的位置(分隔符可以是 ' ' ';' '.' 任何你想要的单引号之间。
添加任意数量的参数。

使用 xargs、cut 和一些 bash 脚本解决了问题。

干杯!

如果你想路过,我有一些有用的提示http://hongouru.blogspot.com

I was looking for a solution for this exact problem and came to the conclution of coding a script in the midle.

to transform the standard output for the next example use the -n '\n' delimeter

example:

 user@mybox:~$ echo "file1.txt file2.txt" | xargs -n1 ScriptInTheMiddle.sh

 inside the ScriptInTheMidle.sh:
 !#/bin/bash
 var1=`echo $1 | cut -d ' ' -f1 `
 var2=`echo $1 | cut -d ' ' -f2 `
 myprogram  "--file1="$var1 "--file2="$var2 

For this solution to work you need to have a space between those arguments file1.txt and file2.txt, or whatever delimeter you choose, one more thing, inside the script make sure you check -f1 and -f2 as they mean "take the first word and take the second word" depending on the first delimeter's position found (delimeters could be ' ' ';' '.' whatever you wish between single quotes .
Add as many parameters as you wish.

Problem solved using xargs, cut , and some bash scripting.

Cheers!

if you wanna pass by I have some useful tips http://hongouru.blogspot.com

九局 2024-10-01 15:34:13

实际上,这相对简单:

... | sed 's/^/--prefix=/g' | sed 's/^/--prefix=/g' | xargs 回显 | xargs -I PARAMS your_cmd PARAMS

sed 's/^/--prefix=/g' 是可选的,以防您需要为每个参数添加 --prefix= 前缀。

xargs echo 将参数行列表(每行一个参数)转换为单行中的参数列表,并且 xargs -I PARAMS your_cmd PARAMS 允许您运行命令,将参数放置在您想要的位置。

所以cat input.txt | sed 's/^/--file=/g' | sed 's/^/--file=/g' | xargs 回声 | xargs -I PARAMS my-program PARAMS 执行您需要的操作(假设 input.txt 中的所有行都很简单并且每行都符合单个参数值)。

Actually, it's relatively easy:

... | sed 's/^/--prefix=/g' | xargs echo | xargs -I PARAMS your_cmd PARAMS

The sed 's/^/--prefix=/g' is optional, in case you need to prefix each param with some --prefix=.

The xargs echo turns the list of param lines (one param in each line) into a list of params in a single line and the xargs -I PARAMS your_cmd PARAMS allows you to run a command, placing the params where ever you want.

So cat input.txt | sed 's/^/--file=/g' | xargs echo | xargs -I PARAMS my-program PARAMS does what you need (assuming all lines within input.txt are simple and qualify as a single param value each).

久伴你 2024-10-01 15:34:13

如果您不知道前面的文件数量,还有另一种好方法可以做到这一点:

my-program $(find . -name '*.txt' -printf "--file=%p ")

There is another nice way of doing this, if you do not know the number of files upront:

my-program $(find . -name '*.txt' -printf "--file=%p ")
活泼老夫 2024-10-01 15:34:13

大多数答案没有考虑到输入行中的某些字符可能会破坏 xargs 和/或不带引号的 $(...)

以下是一些可以正确完成工作(即稳健且高效)的解决方案。


1. PURE BASH

您可以将输入行加载到 bash 数组中,并使用参数扩展将 --file= 添加到每个元素:

readarray -t files < input.txt

my-program "${files[@]/#/--file=}"

警告!< /strong> 不要使用此方法为每个数组元素生成多个参数(例如 ‑f Space xxx.txt)。


2. AWK | XARGS -0

您可以使用 awk 在每行前面添加 --file= 并生成一个 NUL 分隔的流,该流可以由 xargs -0 安全处理:

awk '{printf("--file=%s%c",$0,0)}' input.txt |
xargs -0 my-program

3。 SED | XARGS

如果您需要遵守POSIX

sed -e 's/"/"\\""/g' -e 's/.*/--file="&"/' input.txt |
xargs my-program

Most answers don't take into account that some characters in the input lines can break xargs and/or unquoted $(...).

Here are a few solutions that do the job correctly (i.e. robustly and efficiently).


1. PURE BASH

You can load the input lines into a bash array and prepend --file= to each element with a parameter expansion:

readarray -t files < input.txt

my-program "${files[@]/#/--file=}"

Warning! Don't use this method to generate more than one argument per array element (for e.g. ‑f Space xxx.txt).


2. AWK | XARGS -0

You can use awk to prepend --file= to each line and generate a NUL-delimited stream that can be safely processed by xargs -0:

awk '{printf("--file=%s%c",$0,0)}' input.txt |
xargs -0 my-program

3. SED | XARGS

If you ever need to be POSIX compliant:

sed -e 's/"/"\\""/g' -e 's/.*/--file="&"/' input.txt |
xargs my-program
落墨 2024-10-01 15:34:13

还没有人提到从循环中回显,所以为了完整起见,我将其放入(这将是我的第二种方法, sed 是第一种):

for line in $(< input.txt) ; do echo --file=$line ; done | xargs echo my-program

Nobody has mentioned echoing out from a loop yet, so I'll put that in for completeness sake (it would be my second approach, the sed one being the first):

for line in $(< input.txt) ; do echo --file=$line ; done | xargs echo my-program
风向决定发型 2024-10-01 15:34:13

我发现了一个更直接的方法。您甚至可以根据自己的喜好自定义位置参数的顺序,如下面的演示所示。

set $(cat input.txt)
my-program --file=$1 --file=$3 --file=$2

这在您知道输入中参数的顺序和大小的情况下效果很好。

I discovered a more straightforward way. You can even customize the order of positional parameters to your liking, like in the demonstration below.

set $(cat input.txt)
my-program --file=$1 --file=$3 --file=$2

This works well in scenarios where you know the order and magnitude of arguments that are in the input.

妖妓 2024-10-01 15:34:13

旧的,但这是一个更好的答案:

cat input.txt |
gsed "s/\(.*\)/\-\-file=\1/g" |
tr '\n' ' ' |
xargs my_program

gsed 只是 GNU sed 以确保语法与版本匹配。 brew install gsed 或者只是 sed(如果您已经使用 GNU/Linux)...

测试一下:

cat input.txt |
gsed "s/\(.*\)/\-\-file=\1/g" |
tr '\n' ' ' |
xargs echo my_program

Old but this is a better answer:

cat input.txt |
gsed "s/\(.*\)/\-\-file=\1/g" |
tr '\n' ' ' |
xargs my_program

gsed is just GNU sed to ensure syntax matches version. brew install gsed or just sed if you're on GNU/Linux already...

Test it:

cat input.txt |
gsed "s/\(.*\)/\-\-file=\1/g" |
tr '\n' ' ' |
xargs echo my_program
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文