Nếu bạn từng viết code, dù script shell, Python, C++, hay thậm chí Scratch, bạn biết biến là sống còn. Máy tính và coder dùng biến làm trạm trung chuyển, lén lút truyền thông tin qua lại. Ví dụ, nếu cần xử lý tên user trong shell script, bạn thiết lập biến, डाल tên user vào biến, rồi bảo máy tính làm gì đó với biến (kiểm tra danh sách user được phép, ví dụ). Biến quan trọng vì cho phép code động: chúng là placeholder cho thông tin mong đợi thay đổi mỗi lần chạy code.
Nhưng biến, vì quá phổ biến, cũng trở nên khó kiểm soát. Thường bạn gom nhiều biến trong dự án code đến nỗi gần như không thể theo dõi hết. Bạn dùng quy ước thông minh, như tiền tố tất cả biến liên quan bằng chuỗi chung (user_name, user_pass, user_time...), hoặc tạo danh sách chính ở đâu đó để tra cứu dễ, nhưng chi phí theo dõi tất cả trở nên tiring.
Một câu trả lời truyền thống là mảng (arrays). Chúng hoạt động tốt trong hầu hết ngôn ngữ lập trình, bao gồm ngôn ngữ scripting shell như Bash.
Hầu hết shell cung cấp tạo, thao tác, truy vấn mảng chỉ số (indexed arrays). Bằng ngôn ngữ đơn giản, mảng chỉ số là danh sách các thứ có tiền tố số. Danh sách đó, cùng số gán, gói gọn trong một biến, dễ "mang" trong code.
Bash tuy nhiên bao gồm khả năng tạo mảng liên kết (associative arrays), và xử lý mảng này như mảng khác. Mảng liên kết cho phép tạo danh sách cặp khóa-giá trị, thay vì chỉ giá trị có số.
Bạn gán giá trị cho khóa tùy ý:
$ declare -A userdata
$ userdata[name]=seth
$ userdata[pass]=8eab07eb620533b083f241ec4e6b9724
$ userdata[login]=`date --utc +%s`
Truy vấn bất kỳ khóa:
$ echo "${userdata[name]}"
seth
$ echo "${userdata[login]}"
1583362192
Hầu hết thao tác mảng thông thường đều có. Ví dụ, liệt kê tất cả giá trị:
$ echo "${userdata[*]}"
8eab07eb620533b083f241ec4e6b9724 seth 1583362192
Xem toàn bộ mảng:
$ typeset -A
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A userdata='([pass]="8eab07eb620533b083f241ec4e6b9724"
[name]="seth"
[login]="1583362192" )'
Bạn cũng xóa mục khỏi mảng dùng unset:
$ unset userdata[pass]
$ typeset -A
[...]
declare -A userdata='([name]="seth"
[login]="1583362192" )'
Cuối cùng, hủy toàn bộ mảng.
$ unset "userdata[*]"
Mảng cho dữ liệu
Mảng là công cụ hữu ích lưu dữ liệu liên quan cùng nhau. Bạn dùng biến đơn giản trong hầu hết trường hợp, nhưng đôi khi hợp lý hơn lưu thuộc tính của một "đối tượng" dữ liệu đơn lẻ trong mảng, để dữ liệu gộp chung và có chỉ số. Ví dụ, nếu xử lý tên đăng nhập và thời gian từ utmp, sẽ hữu ích hơn liên kết thời gian đăng nhập với user mà thời gian đó thuộc về, thay vì lưu hai đối tượng dữ liệu riêng biệt không có liên kết rõ ràng.
Hơn nữa, khác với biến, entry trong mảng không cần tồn tại trước khi lưu dữ liệu. Bạn không cần biết chính xác bao nhiêu dữ liệu sẽ lưu trước khi lưu. Đó là lợi thế lớn nếu xử lý dữ liệu không kiểm soát hoặc dự đoán: nếu không biết bao nhiêu user trong utmp từng ngày, khó xây script chứa tất cả entry. Với mảng, chỉ khai báo một mảng và đọc dữ liệu vào, tạo cặp khóa-giá trị mới cho đến khi hết dữ liệu.
Mảng mạnh mẽ, và phổ biến trong ngôn ngữ lập trình ngoài Bash. Bắt đầu dùng ngay!