我们通常$@
用来表示除 $0 之外的所有参数。但是,我不知道什么是数据结构$@
。
为什么$*
在包含双引号时它的行为不同,谁能给我一个解释级别的解释?
可以在for循环中迭代,所以好像是数组。但是,它也可以完全用 simple 回显echo $@
,如果是数组,则只显示第一个元素。由于shell的限制,我无法编写更多的实验代码来执行它。
这篇文章之间的区别:这篇文章展示了$@
与$*
. 但我想知道$@
. Shell 作为一种解释语言,像 Python 一样,应该根据一系列基本类型来表示数据。或者换句话说,我想知道 $@ 是如何存储在计算机内存中的。
它是字符串、多行字符串还是数组?
如果是唯一的数据类型,是否可以将自定义变量定义为该类型的实例?
Sté*_*las 16
这开始是对 Bourne shell 的一次黑客攻击。在 Bourne shell 中,对列表上下文中的所有单词(命令行参数或for
循环循环的单词)进行了 IFS 分词(在标记化之后)。如果你有:
IFS=i var=file2.txt
edit file.txt $var
Run Code Online (Sandbox Code Playgroud)
第二行将被标记为 3 个单词,$var
将被扩展,并且 split+glob 将在所有三个单词上完成,因此您最终将ed
使用t
, f
, le.txt
, f
,le2.txt
作为参数运行。
引用其中的一部分会阻止 split+glob。Bourne shell 最初通过在内部设置第 8 位来记住哪些字符被引用(后来在 Unix 变得 8bit clean 时发生了变化,但 shell 仍然做了类似的事情来记住引用了哪个字节)。
二者$*
并$@
分别将位置参数的级联与-之间的空间。但是有一个特殊的处理$@
when 里面的双引号。如果$1
包含foo bar
和$2
包含baz
,"$@"
将扩展为:
foo bar baz
^^^^^^^ ^^^
Run Code Online (Sandbox Code Playgroud)
(^
上面的s 表示哪些字符设置了第 8 位)。其中第一个空格被引用(设置了第 8 位)而不是第二个空格(在单词之间添加的那个)。
并且 IFS 拆分负责分隔参数(假设$IFS
默认情况下空格字符在其中)。这类似于$*
在其前身 Mashey shell 中的扩展方式(它本身基于 Thomson shell,而 Bourne shell 是从头开始编写的)。
这就解释了为什么在Bourne shell中最初"$@"
将扩展为空字符串,而不是什么都没有的时候位置参数列表是空的(你不得不工作,它与周围的${1+"$@"}
),为什么没有保持空位置参数,为什么"$@"
没'$IFS
不包含空格字符时不起作用。
目的是能够将参数列表逐字传递给另一个命令,但这对于空列表、空元素或$IFS
不包含空格时无法正常工作(前两个问题最终在以后的版本中得到修复)。
Korn shell(POSIX 规范所基于的)以几种方式改变了这种行为:
edit
或file.txt
在上面的示例中的字面词)$*
and当为空时$@
与$IFS
或 空格的第一个字符连接,$IFS
除了带引号的"$@"
,该连接器像在 Bourne shell 中一样不带引号,并且对于带引号的"$*"
whenIFS
为空,位置参数被附加而没有分隔符。${array[@]}
${array[*]}
让人想起了 Bourne's $*
and$@
但从索引 0 而不是 1 开始,并且稀疏(更像是关联数组)这意味着$@
不能真正被视为 ksh 数组(与csh
/ rc
/ zsh
/ fish
/相比,yash
其中$argv
/$*
是正常的数组)。"$@"
when $#
is 0 现在扩展为空字符串而不是空字符串,"$@"
当$IFS
不包含空格时有效,除非 whenIFS
为空。$*
当$IFS
为空时,不带通配符的未加引号扩展为一个参数(其中位置参数与空格连接)。ksh93 修复了上面剩下的几个问题。在 ksh93 中,$*
并$@
扩展为位置参数列表,无论 的值如何都分开$IFS
,然后在列表上下文中进一步 split+globbed+brace-expanded,$*
与 的第一个字节(不是字符)连接$IFS
,"$@"
在列表上下文中扩展为列表的位置参数,而不管 的值$IFS
。在非列表上下文中,如 in var=$@
,$@
无论 的值如何,都与空格连接$IFS
。
bash
的数组是在 ksh 之后设计的。区别在于:
$IFS
代替字节的第一个字符$*
当$IFS
为空时在非列表上下文中未引用时的扩展。虽然 POSIX 规范过去非常模糊,但现在或多或少指定了 bash 行为。
这是从普通数组不同ksh
或bash
在于:
"${@:0}"
包含$0
(不是位置参数,并且在函数中根据 shell 和函数的定义方式为您提供函数的名称))。shift
可以使用。在zsh
或yash
其中阵列是正常阵列(未稀疏,索引从1开始像在所有其他弹但KSH / bash)的,$*
被视为普通阵列。zsh
有$argv
作为它的别名(为了与 兼容csh
)。$*
与$argv
or相同${argv[*]}
(参数与 of 的第一个字符连接$IFS
但在列表上下文中仍分开)。"$@"
喜欢"${argv[@]}"
或"${*[@]}"}
经过 Korn 式特殊处理。
但是,我不知道什么是数据结构
$@
。
这是一个特殊的参数,可以扩展到位置参数的值......但这是对术语的挑剔。
我们可以将位置参数视为 的一部分$@
,因此它具有许多不同的元素 ( $1
, $2
...),可以独立访问并以连续的自然数命名。这使它成为通常称为数组的东西。
但是,语法有点奇怪,甚至是有限的。无法单独修改数组的单个元素。相反,整个事情必须立即设置。(您可以使用set -- "$@" foo
附加值,或set -- "${@:1:2}" foo "${@:3}"
在中间添加值。但在这两种情况下,您都必须写出整个结果列表。)
为什么
$*
在包含双引号时它的行为不同,
因为他们被定义为行为不同。
但是,它也可以完全用 simple 回显
echo $@
,如果是数组,则只显示第一个元素。
如果您的意思是a=(foo bar asdf); echo $a
只输出foo
,那么这主要是 shell 语法的一个怪癖,以及 ksh 样式命名数组的创建时间晚于位置参数 和 的事实$@
。Plain$a
与${a[0]}
so 它具有单个标量值的向后兼容含义相同,无论a
是数组还是简单的标量变量。
@
引用整个列表的符号与命名数组重用,这"${a[@]}"
是获取整个列表的方式。与命名数组相比, with $@
,只是跳过了不必要的大括号和括号以及名称。
或者换句话说,我想知道如何
$@
存储在计算机内存中。
这取决于实现,您必须查看您关心的任何特定 shell 的源代码。
它是字符串、多行字符串还是数组?
一个数组,主要是。尽管与 ksh 样式的命名数组不同,因为它们可以将任意非负整数作为索引,而不仅仅是像$@
. (也就是说,命名数组可以是稀疏的,并且具有例如索引1
, 3
and 4
, with0
和2
missing 。这对于位置参数是不可能的。)
它不是单个字符串,因为它可以扩展为不同的元素,并且调用元素行也不正确,因为任何常规变量或位置参数之一( 的元素$@
)也可以包含换行符。
如果是唯一的数据类型,是否可以将自定义变量定义为该类型的实例?
不。但无论如何命名数组可能更有用。
归档时间: |
|
查看次数: |
1077 次 |
最近记录: |