bash 从管道获取参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17847103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get argument from pipe
提问by Dávid Natingga
Consider having the results from the pipe:
考虑从管道获得结果:
find .
Now I would like to access in the second command behind the pipe what is actually piped (inputed) and then for example to print it twice.
现在我想在管道后面的第二个命令中访问实际管道(输入)的内容,然后例如打印两次。
find . | printf $arg$arg\n
#each filename would be printed twice per line
Please note that the question is not asking about printing whatever once gets from pipe twice, I know how to use bash forloop or write a script that could accomplish the mentioned. How I can get $argto use it quickly in inline scripts?
请注意,问题不是要打印两次从管道中获取的任何内容,我知道如何使用 bash forloop 或编写可以完成上述操作的脚本。如何让 $arg 在内联脚本中快速使用它?
$0 and $1 do not work as they do in scripting files.
$0 和 $1 不像在脚本文件中那样工作。
采纳答案by Pringley
Short answer:You can print each file twice using sed:
简短回答:您可以使用 sed 将每个文件打印两次:
find . | sed 's/.*/& &/'
Sed can edit lines as they are inputted. The above command says s
(substitute) .*
(the entire line) & &
(with itself, twice).
sed 可以编辑输入的行。上面的命令说s
(替换).*
(整行)& &
(与自身,两次)。
Longer answer:When you pipe one program into another, you're connecting the first program's standard output streamto the second program's standard input stream. Anything the first program prints will be treated as input for the second program.
更长的答案:当您将一个程序通过管道传输到另一个程序时,您将第一个程序的标准输出流连接到第二个程序的标准输入流。第一个程序打印的任何内容都将被视为第二个程序的输入。
Unfortunately for your example, the input doesn't come in line-by-line chunks that map nicely to a hypothetical $args
variable. It comes in a big monolithic stream. If you want to print each line of the stream twice, you can use sed (which is a Stream EDitor), but it's just doing line-by-line replacements.
不幸的是,对于您的示例,输入不是以很好地映射到假设$args
变量的逐行块的形式出现。它来自一个巨大的整体流。如果您想将流的每一行打印两次,您可以使用 sed(它是一个流编辑器),但它只是逐行替换。
回答by Jonathan Leffler
Ignoring the possibility that file names contain newlines, you can use sed
as pringleysuggests in his answer, or you can create a while
loop with the read
command:
忽略文件名包含换行符的可能性,您可以sed
按照pringley在他的回答中建议的那样使用,或者您可以while
使用以下read
命令创建一个循环:
find . |
while read -r line
do
echo "$line$line"
done
(The -r
is for 'raw' input; it stops the shell expanding backslash escape sequences in the input, and is a standard POSIX feature of the read
command in the shell.)
(-r
用于“原始”输入;它停止 shell 在输入中扩展反斜杠转义序列,并且是read
shell 中命令的标准 POSIX 功能。)
Since you mention bash
, you can avoid problems with newlines in the file names by using the find . -print0
option to terminate each name by a null byte ('\0'
in C) instead of a newline, and then use:
由于您提到了bash
,您可以通过使用find . -print0
以空字节('\0'
在 C 中)而不是换行符来终止每个名称的选项来避免文件名中的换行符问题,然后使用:
find . -print0 |
while read -r -d '' line
do
echo "X${line}${line}X"
done
The -d ''
replaces the normal newline delimiter with the first character of the string argument, but the string is empty so the first character is the only character is a null byte.
该-d ''
替换字符串参数的第一个字符的正常换行分隔符,但字符串是空的,所以第一个字符是唯一的字符是一个空字节。
There isn't an easy way (nor, as far as I know, a hard way) to use a for
loop along the lines of:
没有一种简单的方法(据我所知,也没有一种困难的方法)来使用for
循环:
for line in $(find .)
do
echo "X${line}${line}X"
done
which works reliably for names with spaces, or newlines in them.
它适用于带有空格或换行符的名称。
Often, you may want to use the xargs
command. This reads standard input and creates a command line using what's read from standard input as arguments to the command.
通常,您可能想要使用该xargs
命令。这读取标准输入并使用从标准输入读取的内容作为命令的参数创建命令行。
find . | xargs wc -l
Or, with newline and space safety (by default, xargs
splits arguments at spaces, tabs and newlines):
或者,使用换行符和空格安全(默认情况下,xargs
在空格、制表符和换行符处拆分参数):
find . -type f -print0 | xargs -0 wc -l
There are a lot of options you can apply to xargs
— especially the GNU version.
您可以应用很多选项xargs
——尤其是 GNU 版本。
However, you also have options to find
that largely make xargs
redundant:
但是,您也可以选择在find
很大程度上使xargs
冗余变得多余:
find . -type f -exec wc -l {} +
which does basically the same job as the find . -print0 | xargs -0 wc -l
command. One difference is that if there are no files in the output from find
, then using -exec
won't execute wc
at all, whereas by default, xargs
will execute it once (with no file name argument; this is for POSIX compliance). With GNU xargs
, you can use -r
or --no-run-if-empty
to stop that happening. Mac OS X xargs
seems to do that anyway.
它与find . -print0 | xargs -0 wc -l
命令的工作基本相同。一个区别是,如果 的输出中没有文件find
,则 using-exec
根本不会执行wc
,而默认情况下,xargs
将执行一次(没有文件名参数;这是为了符合 POSIX)。使用 GNU xargs
,您可以使用-r
或--no-run-if-empty
来阻止这种情况发生。xargs
无论如何,Mac OS X似乎都这样做了。
回答by glenn Hymanman
find . | xargs -I{} printf "%s%s\n" {} {}