Có phải tất cả các biến được lưu trữ trong bộ nhớ dưới dạng chuỗi trong bash?


13

Nói rằng tôi đã tạo các biến sau:

s=John
i=12345
f=3.14

Có phải tất cả các biến này được lưu trữ trong bộ nhớ dưới dạng chuỗi hoặc bashcó các loại dữ liệu khác không?


1
Chỉ cần quan tâm, tại sao nó lại quan trọng? Tôi thực sự không quan tâm nếu chúng được lưu trữ dưới dạng văn bản tiếng Swig miễn là nó không ảnh hưởng đến chức năng của ngôn ngữ (ảnh hưởng đến hiệu suất có thể là một vấn đề, nhưng nếu điều đó quan trọng, thì chúng là công cụ tốt hơn trong kho vũ khí của bạn bash).

2
@paxdiablo Không thành vấn đề, tôi chỉ thắc mắc vì tò mò, vì tất cả các ngôn ngữ lập trình / tập lệnh khác mà tôi biết (ví dụ: Java, C ++, JavaScript, PHP, v.v.) có cách biểu thị bộ nhớ duy nhất cho từng loại dữ liệu , thật thú vị khi thấy một ngôn ngữ kịch bản chỉ có một đại diện bộ nhớ cho tất cả các loại dữ liệu.
dùng268325

Câu trả lời:


16

Các biến Bash được tháo ra .

Không giống như nhiều ngôn ngữ lập trình khác, Bash không phân tách các biến của nó theo "loại". Về cơ bản, các biến Bash là các chuỗi ký tự, nhưng, tùy thuộc vào ngữ cảnh, Bash cho phép các phép toán số học và so sánh trên các biến. Yếu tố xác định là giá trị của một biến chỉ chứa các chữ số.

Như một câu trả lời khác nói , có loại hình đánh máy yếudeclare .

Đây là một hình thức rất yếu của việc gõ [1] có sẵn trong các ngôn ngữ lập trình nhất định.

Xem một ví dụ:

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.

Người giới thiệu:


13

Bash về cơ bản có các biến vô hướng đơn giản, mảng và mảng kết hợp. Ngoài ra, vô hướng có thể được gắn thẻ dưới dạng số nguyên với declarenội dung . Từ quan điểm của người lập trình / trình bao kịch bản, các biến chuỗi đóng vai trò là chuỗi, biến số nguyên đóng vai trò là số nguyên và mảng tương ứng với loại của chúng. Việc thực hiện nội bộ không liên quan lắm.


Nhưng, nếu chúng ta muốn biết làm thế nào dữ liệu thực sự được lưu trữ trong bộ nhớ, chúng ta phải kiểm tra mã nguồn để xem chương trình thực sự làm gì.

Trong Bash 4.4, vô hướng được lưu trữ dưới dạng chuỗi, bất kể thẻ số nguyên. Điều này có thể nhìn thấy trong định nghĩa của struct variable/ SHELL_VARtypedef và trong hàmmake_variable_value , dịch rõ ràng các số nguyên thành chuỗi để lưu trữ.

Mảng được lưu trữ trong những gì trông giống như một danh sách được liên kết ( array.h) và các mảng kết hợp dưới dạng bảng băm. Các giá trị trong chúng một lần nữa được lưu trữ dưới dạng chuỗi. Việc lựa chọn một danh sách được liên kết cho các mảng có vẻ kỳ lạ, nhưng vì các mảng có thể thưa thớt và các chỉ mục có thể là các số tùy ý cho dù mảng có chứa bao nhiêu phần tử, sự lựa chọn thiết kế đó dễ hiểu hơn một chút.

Tuy nhiên, mã cũng chứa một định nghĩa cho người không sử dụngunion _value , với các trường cho số nguyên, số dấu phẩy động, cũng như các giá trị chuỗi. Nó được đánh dấu trong một nhận xét là "cho tương lai", vì vậy có thể một số phiên bản tương lai của Bash sẽ lưu trữ các loại vô hướng khác nhau trong các hình thức bản địa của chúng.


1

Đối với cuộc sống của tôi, tôi không thể tìm thấy điều này được nêu ở bất cứ đâu trong rất nhiều từ nhưng đây là cách tôi hiểu nó.

Bash là một trình thông dịch, không phải là trình biên dịch và biểu diễn tất cả các biến dưới dạng chuỗi. Do đó tất cả các nỗ lực và nhấn mạnh đi cùng với việc mở rộng các loại.

Bash chuyển tất cả các biến được đặt tên declarethành chuỗi với các thuộc tính kiểm soát cách biến đó được mở rộng bằng cách declarelưu trữ.

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" )

Và tất nhiên

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

Coda cho điều này là ngay cả khi declarecó một biểu diễn bên trong thay đổi với các cờ thuộc tính, các chuỗi là tất cả những gì bash nhìn thấy hoặc muốn xem.



0

Nó không liên quan.

Cách duy nhất để tương tác với các biến Bash là thông qua Bash, do đó bạn không thể nhận thấy bất kỳ sự khác biệt nào về cách các biến được lưu trữ trong bộ nhớ, bởi vì bạn không bao giờ có thể truy cập chúng trực tiếp qua bộ nhớ , bạn luôn cần phải hỏi Bash về chúng giá trị, và Bash sau đó có thể dịch chúng trong bất cứ cách nào họ muốn trông như thể họ đã được lưu trữ trong bất kỳ cách nào cụ thể.

Trong thực tế, họ có thể không được lưu trữ trong bộ nhớ ở tất cả . Tôi không biết các cách triển khai phổ biến của Bash là thông minh như thế nào, nhưng ít nhất có thể trong các trường hợp đơn giản để xác định liệu một biến sẽ được sử dụng và / hoặc liệu nó sẽ được sửa đổi, và tối ưu hóa nó hoàn toàn hay bỏ qua nó.


Tôi nghĩ rằng điểm của câu hỏi là đại diện chứ không phải là địa điểm
bu5hman

2
Quan điểm của tôi là bạn không thể biết đại diện, bởi vì bạn không thể quan sát nó. Vì vậy, nó không liên quan và nó có thể thay đổi mà bạn không bao giờ nhận thấy. Đơn giản là không thể nói đại diện mà Bash có thể chọn. Bạn có thể đi sâu vào mã nguồn của một triển khai và kiểm tra xem nó chọn đại diện nào, nhưng nó có thể thay đổi đại diện vào ngày mai trong bản phát hành bản vá tiếp theo và sẽ không có cách nào để bạn biết.
Jörg W Mittag

Biến Schrotingers? Tôi đồng ý với bạn về cơ bản về việc đại diện cơ bản là không liên quan (xem câu trả lời của tôi) nhưng khi sử dụng bash, chúng tôi thực sự 'mã hóa cho một giao diện' và việc biểu diễn tại giao diện rất nghiêm ngặt.
bu5hman

2
Có, nhưng câu hỏi không phải là về biểu diễn ở ranh giới giao diện, mà cụ thể là về cách chúng được "lưu trữ trong bộ nhớ". Và với câu hỏi đó, tôi sẽ trả lời: chúng ta không, không thể và không nên biết.
Jörg W Mittag

Điều này diễn giải dòng cuối cùng của bài đăng của tôi ..... như tôi đã nói, chúng tôi đồng ý ...... và đưa ra đại diện cho OP và bản chất của câu hỏi, tôi nghĩ rằng họ sẽ được chấm điểm hợp lý cho bài tập về nhà của họ, bất cứ ai được trích dẫn ;-).
bu5hman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.