xargs将stdin转换为命令行参数

      我们可以用管道将一个命令的stdout(标准输出)重定向到另一个命令的stdin(标准输入)。例如:

$cat  foo.txt |  grep  “test”

      但是,有些命令只能以命令行参数的形式接受收据,而无法通过stdin接受数据流。在这种情况下,我们没法用管道来提供那些只有通过命令行参数才能提供的数据。

      只有另辟蹊径。xargs是一个很有用的命令,它擅长将标准输入数据转换成命令行参数。

      单行命令是一个命令序列,各命令之间不使用分号,而是使用管道操作符进行连接。精心编写的单行命令可以更高效、更简捷地完成任务。就文本处理而言,需要具备扎实的理论和实践才能够写出适合的单行命令解决方法。xargs就是构建单行命令的重要组件之一。

      xargs命令用该紧跟在管道操作符之后。它以标准输入作为主要的源数据流。

command  | xargs

 

----->>

xargs命令能将stdin接收到的数据重新格式化,再将其作为参数提供给其他命令。

xargs如何格式化数据:

-d选项,指明定界符

-n选项,指明每行最大的参数数量n

范例:将多行输入转换成单行输出

只需将换行符移除,在用” ”(空格)进行替换,就可以实现。xargs默认将空格作为定界符。xargs没有指定参数时,默认能将换行符替换成空格。

$cat  example.txt

1  2 3  4  5  6

7  8 9  10

11  12

$catexample.txt  |  xargs

1  2 3  4  5 6  7  8 9  10  11  12

范例:将单行输入转换成多行输出

$cat  examole.txt  | xargs  -n  3

1  2  3

4  5  6

7  8  9

10  11  12

 

$echo  “splitXsplitXsplitXsplit”  | xargs  -d  X

split splitsplit split

$echo  “splitXsplitXsplitXsplit”  | xargs  -d  X –n 2

split split

split split

xargs的初衷是将参数列表转换成小块分段传给其他命令,以避免参数列表过长。

 

编制一个定制版的echo来更好的理解xargs。

#!/bin/bash

#myecho.sh

echo  $*’#’

当参数被传递给myecho.sh后,它会将这些参数打印出来,并以#字符作为结尾。例如:

$./myecho.sh  arg1 arg2

arg1  arg2#

看下面问题:

有一个包含参数列表的文件(每行一个参数)。

每次提供一个参数:

./myecho.sh  arg1

./myecho.sh  arg2

./myecho.sh arg3

每次提供多个参数:

./myecho.sh  arg1  arg2

./myecho.sh  arg3

一次性提供:

./myecho.sh  arg1 arg2  arg3

上面的问题,也可以用xargs实现。我们将参数保存到args.txt。

$cat  args.txt

arg1

arg2

arg3

$cat  args.txt |  xargs  -n 1  ./myecho.sh

arg1#

arg2#

arg3#

通过#号,可以知道myecho.sh运行了3次。

$cat  args.txt |  xargs  -n 2  ./myecho.sh

arg1  arg2#

arg3#

#catargs.txt  |  xargs ./myecho.sh

arg1  arg2 arg3#

xargs不加参数时,默认将换行符替换成空格。就好像是默认,为这种,从参数列表文件中获取参数提供方便服务的。(想想,如果没有这种默认服务,那么想要将拥有多行文本的args.txt中的参数一次性提取,你会怎么做?)

 

上面例子中,我们直接为myecho.sh提供参数。这些参数都源于args.txt文件。但实际上除了它们外,我们还需要一些固定不变的命令参数。思考下面这种命令格式:

./myecho.sh  -p arg1 –l

在上面的命令执行过程中,arg1是唯一的可变文本,其余部分保持不变。我们应该从args.txt中读取参数,并按照下面的方式提供给命令:

./myecho.sh  -p  arg1 -l

./myecho.sh  -p  arg2 -l

./myecho.sh  -p  arg3 -l

xargs有一个选项-I,可以提供上面这种形式的命令执行序列。我们可以用-I执行一个替换字符串,这个字符串在xargs扩展时会被替换掉。当-I与xargs结合使用,对于每一个参数命令都会执行一次。

$cat  args.txt  | xargs  -I  {} ./myecho.sh  -p  {}  -l

-p  arg1  -l#

-p  arg2  -l#

-p  arg3  -l#

 

 

结合find使用xargs:

两者结合使用可以让任务变得更轻松。不过,人们通常却是以一种错误的组合方式使用它们。例如:

$find  .  –type f  -name  “*.txt” -print  | xargs  rm  -f

这样做很危险。有时可能会删除不必要删除的文件。我们没法预测分隔find命令输出结果的定界符究竟是’\n’还是’  ‘(空格)。很多文件名中都可能会包含空格符,而xargs很可能会误认为它们是定界符(例如,hell text.txt会被xargs误认为hell和text.txt)。

只要我们把find的输出作为xargs的输入,就必须将-print0与find结合使用,以字符null来分隔输出。

用find匹配并列出所有.txt文件,然后用xargs将这些文件删除:

$find  .  –type f  -name  “*.txt” -print0  |  xargs -0  rm  -f

删除所有txt文件。xargs  -0将\0作为输入定界符。

统计所有C程序文件的行数:

$find  code_path  -type -f  -name  “*.c” -print0  |  xargs -0  wc  -l

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章