从管道获取参数

Dáv*_*gga 8 bash pipe xargs

考虑从管道获得结果:

find .
Run Code Online (Sandbox Code Playgroud)

现在我想在管道后面的第二个命令中访问实际上是管道(输入)然后例如打印两次.

find . | printf $arg$arg\n
#each filename would be printed twice per line
Run Code Online (Sandbox Code Playgroud)

请注意,问题不是要求打印一次从管道中获取两次,我知道如何使用bash for循环或编写可以完成上述操作的脚本.如何让$ arg在内联脚本中快速使用它?

$ 0和$ 1不像脚本文件那样工作.

Jon*_*ler 9

忽略的可能性,文件名包含换行符,你可以使用sed如pringley建议在他的回答,也可以创建一个while与循环read命令:

find . |
while read -r line
do
    echo "$line$line"
done
Run Code Online (Sandbox Code Playgroud)

(-r用于'原始'输入;它会停止shell在输入中扩展反斜杠转义序列,并且是readshell中命令的标准POSIX功能.)

自提到以来bash,通过使用find . -print0选项以空字节('\0'在C中)而不是换行符终止每个名称,可以避免文件名中的换行问题,然后使用:

find . -print0 |
while read -r -d '' line
do
    echo "X${line}${line}X"
done
Run Code Online (Sandbox Code Playgroud)

在-d ''这样的第一个字符是唯一的字符是一个空字节替换正常的换行分隔符与字符串参数的第一个字符,但字符串是空的.

根据以下方法使用for循环并不是一种简单的方法(也不是,据我所知,很难).

for line in $(find .)
do
    echo "X${line}${line}X"
done
Run Code Online (Sandbox Code Playgroud)

对于带有空格或其中的换行符的名称,它可靠地工作.

通常,您可能希望使用该xargs命令.这将读取标准输入并使用从标准输入读取的内容作为命令的参数创建命令行.

find . | xargs wc -l
Run Code Online (Sandbox Code Playgroud)

或者,使用换行和空间安全(默认情况下,xargs在空格,制表符和换行符处拆分参数):

find . -type f -print0 | xargs -0 wc -l
Run Code Online (Sandbox Code Playgroud)

您可以应用很多选项xargs- 尤其是GNU版本.

但是,你也有选择,find在很大程度上使xargs多余的:

find . -type f -exec wc -l {} +
Run Code Online (Sandbox Code Playgroud)

它与find . -print0 | xargs -0 wc -l命令的工作基本相同.一个区别是,如果输出中没有文件find,那么使用-exec将根本不执行wc,而默认情况下,xargs将执行一次(没有文件名参数;这是为了符合POSIX).使用GNU xargs,您可以使用-r或--no-run-if-empty停止发生这种情况.xargs无论如何,Mac OS X 似乎也是如此.


小智 5

简答:您可以使用sed打印每个文件两次:

find . | sed 's/.*/& &/'
Run Code Online (Sandbox Code Playgroud)

Sed可以在输入时编辑行.上面的命令说s(替换).*(整行)& &(自己,两次).

更长的答案:当您将一个程序传送到另一个程序时,您将第一个程序的标准输出流连接到第二个程序的标准输入流.第一个程序打印的任何内容都将被视为第二个程序的输入.

不幸的是,对于您的示例,输入不是逐行排列的,这些块可以很好地映射到假设$args变量.它有一个巨大的整体流.如果要打印两次流的每一行,可以使用sed(这是一个Stream EDitor),但它只是逐行替换.