bash中所有变量是否都以字符串形式存储在内存中?


14

假设我创建了以下变量:

s=John
i=12345
f=3.14

所有这些变量是否都以字符串形式存储在内存中,或者是否bash具有其他数据类型?


1
只是出于兴趣,这为什么重要?我真的很在乎它们是否存储为斯瓦希里语文本,只要它不影响该语言的功能即可(影响性能可能是一个问题,但是,如果这很重要,它们是您军械库中比其更好的工具bash)。

2
@paxdiablo没关系,我只是出于好奇而问,因为我所知道的所有其他编程/脚本语言(例如:Java,C ++,JavaScript,PHP等)对于每种数据类型都具有唯一的内存表示形式,因此有趣的是,一种脚本语言对于所有数据类型仅具有一种内存表示形式。
user268325 '18

Answers:


16

Bash变量是无类型的

与许多其他编程语言不同,Bash不会按“类型”分隔其变量。本质上,Bash变量是字符串,但是根据上下文,Bash允许对变量进行算术运算和比较。决定因素是变量的值是否仅包含数字。

作为另一个回答说,有一种弱形式打字的declare

这是某些编程语言中可用的非常弱的类型[1]。

看一个例子:

declare -i number
# The script will treat subsequent occurrences of "number" as an integer.     

number=3
echo "Number = $number"     # Number = 3

number=three
echo "Number = $number"     # Number = 0
# Tries to evaluate the string "three" as an integer.

参考文献:


13

Bash本质上具有简单的标量变量,数组和关联数组。另外,标量可以使用declare内置标记为整数。从脚本程序员/ shell用户的角度来看,字符串变量充当字符串,整数变量充当整数,并且数组根据类型而定。内部实现不是很相关。


但是,如果我们想知道数据是如何实际存储在内存中的,则必须检查源代码以查看程序的实际作用。

在Bash 4.4中,标量存储为字符串,而与整数标记无关。这在/ typedef定义struct variableSHELL_VAR函数中make_variable_value可见,该函数将整数显式转换为字符串以进行存储。

数组存储在看似链表(array.h)的位置,而关联数组存储为哈希表。它们中的值再次存储为字符串。为数组选择链接列表似乎有些奇怪,但是由于数组可能稀疏,并且索引可以是任意数字,而不管数组包含多少元素,因此这种设计选择更容易理解。

但是,该代码还包含未使用union _value的定义,其中包含整数,浮点数和字符串值的字段。它在注释中标记为“ for the future”,因此某些将来的Bash版本可能会以其本机形式存储不同类型的标量。


1

对于我的一生,我找不到这么多话在任何地方说过,但这就是我的理解方式。

Bash是解释器,而不是编译器,并且将所有变量表示为字符串。因此,伴随着各种扩展的所有努力和重点。

击传递经过的所有命名变量declare与字符串属性是控制变量是如何被扩展declare存储设备。

banana=yellow              #no call to declare
declare -p banana
declare -- banana="yellow" #but declare was invoked with --

declare -i test=a          #arithmetic expansion to null/zero
declare -p test
declare -i test="0"

declare -i test2=5+4       #successful arithmetic expansion
declare -p test2
declare -i test2="9"

declare -i float=99.6      #arithmetical expansion fails due to syntax
bash: declare: 99.6: syntax error: invalid arithmetic operator (error token is ".6")

nofloat=99.9
declare -p nofloat
declare -- nofloat"99.6"   #Success because arithmetical expansion not invoked

declare -a a               #variable is marked as a placeholder to receive an array
declare -p a
declare -a a

a[3]=99                    #array elements are appended
a[4]=99
declare -p a
declare -a a=([3]="99" [4]="99") 

declare -A newmap          #same as -a but names instead of numbers
newmap[name]="A Bloke"
newmap[designation]=CFO
newmap[company]="My Company"
declare -p newmap
declare -A newmap=([company]="My Company" [name]="A Bloke" [designation]="CFO" )

而且当然

declare -ia finale[1]=9+16
declare -p finale
declare -ai finale=([1]="25")

可以肯定的是,即使declare内部表示随属性标志而变化,bash看到或想要看到的也是字符串。



0

这无关紧要。

与Bash变量进行交互的唯一方法是通过Bash,因此您不可能注意到变量在内存中的存储方式有何不同,因为您永远无法直接通过内存访问变量,因此始终需要向Bash询问它们的变量。那么价值,Bash可以以任何方式就是了翻译它们看起来好像他们已经被存储在任何特定的方式。

实际上,它们甚至可能根本不存储在内存。我不知道Bash的通用实现有多么聪明,但是至少在简单的情况下,有可能确定是否使用变量和/或是否对其进行修改,然后对其进行完全优化或内联。


我认为问题的重点是表示形式而不是位置
bu5hman

2
我的观点是,您无法了解表示形式,因为您无法观察到它。因此,它是无关紧要的,它可能会在您没有注意到的情况下发生变化。根本无法确定Bash可能选择哪种表示形式。您可以深入研究实现的源代码,并查看它选择了哪种表示形式,但是明天可能会在下一个补丁程序发行版中更改表示形式,并且您将无法知道。
约尔格W¯¯米塔格

薛定ers变量?我确实从根本上同意您的观点,即底层表示形式无关紧要(请参见我的回答),但是在使用bash时,我们实际上是在“编码到接口”,并且接口上的表示形式很严格。
bu5hman

2
是的,但问题是不是在接口边界表示,但具体有关他们是如何“存储在内存中”。关于这个问题,我会回答:我们不知道,不应该知道,不应该知道。
约尔格W¯¯米塔格

改写我自己帖子的最后一行.....正如我说的,我们同意...,并考虑到操作代表和问题的性质,无论他们是谁,我都将给他们合理的分数被引用;-)。
bu5hman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.