2012-08-17 42 views
10

Tôi đã viết một hàm KornShell mẫu để tách một String, đặt nó vào một mảng và sau đó in ra các giá trị. Mã này là như sauPhạm vi của các biến trong KSH

#!/usr/bin/ksh 

splitString() { 

    string="[email protected];[email protected];[email protected]" 

    oIFS="$IFS"; 
    IFS=';' 
    set -A str $string 
    IFS="$oIFS" 
} 

splitString 
echo "strings count = ${#str[@]}" 
echo "first : ${str[0]}"; 
echo "second: ${str[1]}"; 
echo "third : ${str[2]}"; 

Bây giờ echo không in ra các giá trị của mảng, vì vậy tôi cho rằng nó có cái gì để làm với phạm vi của mảng được xác định.

Tôi mới sử dụng Shell scripting, bất kỳ ai cũng có thể giúp tôi hiểu được phạm vi biến trong ví dụ trên không?

+0

Gotcha !!!! Tập lệnh hiện đang hoạt động, không có vấn đề gì với nó. Đã thực hiện một sai lầm nhỏ trong việc gọi hàm theo cách sai. Tuy nhiên, vẫn muốn hiểu phạm vi của các biến trong KSH – Vivek

Trả lời

16

Phạm vi mặc định của biến là toàn bộ tập lệnh.

Tuy nhiên, khi bạn khai báo một biến bên trong một hàm, biến sẽ trở thành cục bộ cho hàm khai báo nó. Ksh có dynamic scoping, do đó, biến cũng có thể truy cập được trong các hàm được gọi bởi hàm khai báo biến. Điều này được ghi lại trong section on functions in the manual. Lưu ý rằng trong AT & T ksh (ngược với pdksh và các dẫn xuất, và các tính năng tương tự của bash và zsh), điều này chỉ áp dụng cho các hàm được xác định với từ khóa function, không cho các hàm được xác định với cú pháp truyền thống f() { … }. Trong AT & T ksh93, tất cả các biến được khai báo trong các hàm được xác định bằng cú pháp truyền thống là toàn cầu.

Cách chính để khai báo biến là với typesetbuiltin. Nó luôn tạo một biến cục bộ (trong AT & T ksh, chỉ trong các hàm được khai báo với function). Nếu bạn gán cho một biến mà không khai báo nó với typeset, nó là toàn cục.

Tài liệu ksh không chỉ định liệu set -A có biến cục bộ hay toàn cầu hay không và các phiên bản khác nhau cũng sẽ làm cho nó trở thành. Theo ksh 93u, pdksh hoặc mksh, biến là toàn cục và tập lệnh của bạn không in ra giá trị. Bạn dường như có ksh88 hoặc phiên bản cũ hơn của ksh, nơi phạm vi là cục bộ. Tôi nghĩ rằng việc khởi tạo str bên ngoài hàm sẽ tạo ra một biến toàn cầu, nhưng tôi không chắc chắn.

Lưu ý rằng bạn nên sử dụng biến cục bộ để ghi đè giá trị IFS: lưu vào biến khác không chỉ vụng về, nó còn giòn vì không khôi phục được IFS đúng cách nếu không được đặt. Hơn nữa, bạn nên tắt globbing, bởi vì nếu không, nếu chuỗi chứa các ký tự bao quanh shell ?*\[ và một trong các từ xảy ra để khớp với một hoặc nhiều tệp trên hệ thống của bạn, nó sẽ được mở rộng, ví dụ: set -A $string trong đó stringa;* sẽ dẫn đến str chứa danh sách tên tệp trong thư mục hiện tại.

set -A str 
function splitString { 
    typeset IFS=';' globbing=1 
    case $- in *f*) globbing=;; esac 
    set -f 
    set -A str $string 
    if [ -n "$globbing" ]; then set +f; fi 
} 
splitString "$string" 
+0

Bạn đang sử dụng cú pháp hàm POSIX. Trong ksh93, nếu bạn sử dụng 'function splitSpring {...}' thì việc scoping với 'typeset' sẽ hoạt động tốt, nếu không thì typeset được bỏ qua cho mục đích scoping. – cdarke

+0

@cdarke Bạn nói đúng, cảm ơn. Bạn có biết tình hình trong ksh88 không? Tôi không thể tái tạo hành vi mà người hỏi mô tả trong ksh93. – Gilles

+0

Trong ksh88 (và bash) phạm vi hoạt động giống nhau cho cả hai kiểu khai báo hàm. Trong ksh93 cú pháp hàm POSIX có chức năng POSIx và không có gì khác, do đó việc truy tìm chức năng cũng bị ảnh hưởng. – cdarke

2

Các biến thường là toàn cầu đối với trình bao mà chúng được xác định từ thời điểm chúng được xác định.

Lệnh typeset có thể làm cho họ địa phương để các chức năng họ quy định tại, hoặc cách khác để làm cho họ tự động xuất khẩu (ngay cả khi họ đang được cập nhật.)

Đọc "câu chữ" và "nguyên" trong manpage, hoặc cuốn sách của Korn.

+0

Cảm ơn Abe về mẹo.Tôi sẽ thực hiện kiểm tra trên manpage – Vivek