当 IFS 设置为某项时,如何将新行传递给 argv 参数,就像命令输出在此处所做的那样?
How can I pass new lines to an argv parameter when IFS is set to something, the way command output does here?
当 IFS 设置为某项时,我如何将新行传递给 argv 参数,就像这里命令输出的方式一样?
请注意,我这样做是为了尝试弄清楚 unix 中的工作原理。并不是说我实际上想要在 argv 的元素中换行!
我有这个显示 argv 的程序。
$ cat blah.c
#include <stdio.h>
int main(int argc, char *argv[]) {
int i = 0;
while (argv[i]) {
printf("argv[%d] = %s\n", i, argv[i]);
i++;
}
return 0;
}
$
$gcc blah.c -o blah
$
我注意到,如果我将 IFS 设置为等于某个值,甚至只是 IFS=
或 IFS=\n
除默认值 unset IFS
之外的任何值,例如IFS="{" 然后命令输出扩展将多行设置为一个参数,例如到 argv[1]
ubuntu@ubuntu:~/aaa$ IFS="{"
ubuntu@ubuntu:~/aaa$
ubuntu@ubuntu:~/aaa$ ./blah `find .`
argv[0] = ./blah
argv[1] = .
./blah
./blah.c
./b
./a
现在,如果我尝试将参数传递给 ./blah,那么我无法在 argv[1] 中获取多行! (我有兴趣做,作为测试)
ubuntu@ubuntu:~/aaa$ ./blah "g h"
argv[0] = ./blah
argv[1] = g h
ubuntu@ubuntu:~/aaa$ ./blah g h
argv[0] = ./blah
argv[1] = g
argv[2] = h
ubuntu@ubuntu:~/aaa$ ./blah g\n h
argv[0] = ./blah
argv[1] = gn
argv[2] = h
ubuntu@ubuntu:~/aaa$ ./blah "g\n h"
argv[0] = ./blah
argv[1] = g\n h
ubuntu@ubuntu:~/aaa$
那么,find .
扩展到什么,即引导多行发送到 argv[1]?
当我尝试将参数传递给程序时无法重现该现象?
当 IFS 不包含 spaces(白色 space)时,命令行上的扩展不会在 spaces 上拆分:
$ var="Hello world"
$ set -x; printf '%s\n' $var; set +x
+ printf '%s\n' Hello world
Hello
world
+ set +x
正如您从 (+
) 输出(-x
输出)中看到的那样,参数 $var
,一个参数,在 space 上被拆分,并且然后打印为几个参数。
如果 IFS 发生变化:
$ IFS=o
$ set -x; printf '%s\n' $var; set +x
+ printf '%s\n' Hell ' w' rld
Hell
w
rld
+ set +x
参数的数量和值也发生变化。
find .
发生的事情是,当IFS包含一个换行符时,是的,IFS的默认值应该包含一个换行符:
$ printf '%s' "$IFS" | od -tcx1
0000000 \t \n
20 09 0a
0000003
查找的输出。 (包括几个换行符)按换行符划分(有效地,换行符被删除)
$ printf '<%s>\n' `find .`
<.>
<./hello>
如果当前目录(pwd)中只有一个名为hello
的文件。
但是,如果 IFS 中的换行符被移除,输出不会被分割,它只是 一个 字符串(包含换行符,是的):
$ IFS=x
$ printf '<%s>\n' `find .`
<.
./hello>
效果类似于引用 find ,
的扩展:
$ IFS=$' \t\n' # return IFS to default in bash.
$ printf '<%s>\n' "`find .`"
<.
./hello>
因此,回答标题的初始问题:
只需使用正确的引号:
$ var='hello world
and some other'
$ printf '<%s>\n' '$var' "$var" $var
<$var>
<hello world
and some other>
<hello>
<world>
<and>
<some>
<other>
这有帮助吗?
当 IFS 设置为某项时,我如何将新行传递给 argv 参数,就像这里命令输出的方式一样?
请注意,我这样做是为了尝试弄清楚 unix 中的工作原理。并不是说我实际上想要在 argv 的元素中换行!
我有这个显示 argv 的程序。
$ cat blah.c
#include <stdio.h>
int main(int argc, char *argv[]) {
int i = 0;
while (argv[i]) {
printf("argv[%d] = %s\n", i, argv[i]);
i++;
}
return 0;
}
$
$gcc blah.c -o blah
$
我注意到,如果我将 IFS 设置为等于某个值,甚至只是 IFS=
或 IFS=\n
除默认值 unset IFS
之外的任何值,例如IFS="{" 然后命令输出扩展将多行设置为一个参数,例如到 argv[1]
ubuntu@ubuntu:~/aaa$ IFS="{"
ubuntu@ubuntu:~/aaa$
ubuntu@ubuntu:~/aaa$ ./blah `find .`
argv[0] = ./blah
argv[1] = .
./blah
./blah.c
./b
./a
现在,如果我尝试将参数传递给 ./blah,那么我无法在 argv[1] 中获取多行! (我有兴趣做,作为测试)
ubuntu@ubuntu:~/aaa$ ./blah "g h"
argv[0] = ./blah
argv[1] = g h
ubuntu@ubuntu:~/aaa$ ./blah g h
argv[0] = ./blah
argv[1] = g
argv[2] = h
ubuntu@ubuntu:~/aaa$ ./blah g\n h
argv[0] = ./blah
argv[1] = gn
argv[2] = h
ubuntu@ubuntu:~/aaa$ ./blah "g\n h"
argv[0] = ./blah
argv[1] = g\n h
ubuntu@ubuntu:~/aaa$
那么,find .
扩展到什么,即引导多行发送到 argv[1]?
当我尝试将参数传递给程序时无法重现该现象?
当 IFS 不包含 spaces(白色 space)时,命令行上的扩展不会在 spaces 上拆分:
$ var="Hello world"
$ set -x; printf '%s\n' $var; set +x
+ printf '%s\n' Hello world
Hello
world
+ set +x
正如您从 (+
) 输出(-x
输出)中看到的那样,参数 $var
,一个参数,在 space 上被拆分,并且然后打印为几个参数。
如果 IFS 发生变化:
$ IFS=o
$ set -x; printf '%s\n' $var; set +x
+ printf '%s\n' Hell ' w' rld
Hell
w
rld
+ set +x
参数的数量和值也发生变化。
find .
发生的事情是,当IFS包含一个换行符时,是的,IFS的默认值应该包含一个换行符:
$ printf '%s' "$IFS" | od -tcx1
0000000 \t \n
20 09 0a
0000003
查找的输出。 (包括几个换行符)按换行符划分(有效地,换行符被删除)
$ printf '<%s>\n' `find .`
<.>
<./hello>
如果当前目录(pwd)中只有一个名为hello
的文件。
但是,如果 IFS 中的换行符被移除,输出不会被分割,它只是 一个 字符串(包含换行符,是的):
$ IFS=x
$ printf '<%s>\n' `find .`
<.
./hello>
效果类似于引用 find ,
的扩展:
$ IFS=$' \t\n' # return IFS to default in bash.
$ printf '<%s>\n' "`find .`"
<.
./hello>
因此,回答标题的初始问题:
只需使用正确的引号:
$ var='hello world
and some other'
$ printf '<%s>\n' '$var' "$var" $var
<$var>
<hello world
and some other>
<hello>
<world>
<and>
<some>
<other>
这有帮助吗?