Mở rộng một biến vỏ và hiệu ứng của toàn cầu và phân chia trên nó


18

Bài đăng này thực sự chứa hai câu hỏi riêng biệt nhưng tôi nghĩ rằng việc nhóm chúng lại với nhau sẽ cung cấp thêm một số bối cảnh. Tôi đã trải qua câu hỏi này về các trích dẫn xung quanh các biến nhưng tôi hoàn toàn không hiểu ý nghĩa của việc mở rộng biến ở vị trí đầu tiên. Vì vậy, câu hỏi đầu tiên của tôi là:

  1. Là gì biến mở rộng trong unix / linux speak?

Phần thứ hai của câu hỏi của tôi liên quan đến các điều khoản sau đây:

  1. toàn cầu
  2. chia

Điều này có nghĩa gì và làm thế nào để chúng ảnh hưởng đến việc mở rộng biến? Câu trả lời cho câu hỏi ban đầu đề cập đến như sau:

Hãy nghĩ về sự vắng mặt của dấu ngoặc kép (trong ngữ cảnh danh sách) là toán tử split + global.

Như thể echo $ test là echo global (split ("$ test")).

Tôi không thể tìm thấy bất kỳ câu trả lời trực tiếp đề cập đến các khái niệm về globbingtách nhưng thay vì sử dụng những thuật ngữ trực tiếp trong việc trả lời các câu hỏi khác như thế này một gần đây .


Câu trả lời:


15

Mở rộng biến (thuật ngữ tiêu chuẩn là mở rộng tham số và đôi khi còn được gọi là thay thế biến ) về cơ bản có nghĩa là thay thế biến bằng giá trị của nó. Chính xác hơn, nó có nghĩa là thay thế $VARIABLEcấu trúc (hoặc ${VARIABLE}hoặc ${VARIABLE#TEXT}các cấu trúc khác) bằng một số văn bản khác được xây dựng từ giá trị của biến. Văn bản khác này là sự mở rộng của biến.

Quá trình mở rộng diễn ra như sau. (Tôi chỉ thảo luận về trường hợp phổ biến, một số cài đặt shell và tiện ích mở rộng sửa đổi hành vi.)

  1. Lấy giá trị của biến, đó là một chuỗi. Nếu biến không được xác định, sử dụng chuỗi rỗng.
  2. Nếu cấu trúc bao gồm một chuyển đổi, áp dụng nó. Ví dụ: nếu cấu trúc là ${VARIABLE#TEXT}và giá trị của biến bắt đầu bằng TEXT, hãy xóa TEXTkhỏi đầu giá trị.
  3. Nếu ngữ cảnh yêu cầu một từ đơn (ví dụ trong dấu ngoặc kép hoặc ở phía bên phải của bài tập hoặc bên trong tài liệu ở đây), hãy dừng ở đây. Nếu không tiếp tục với các bước tiếp theo.
  4. Chia giá trị thành các từ riêng biệt ở mỗi chuỗi khoảng trắng. (Biến IFScó thể được thay đổi thành tách tại các ký tự khác với khoảng trắng.) Kết quả là do đó không còn là một chuỗi, mà là một danh sách các chuỗi. Danh sách này có thể trống nếu giá trị chỉ chứa khoảng trắng.
  5. Hãy coi mỗi thành phần của danh sách là một mẫu ký tự đại diện tên tệp, tức là một quả địa cầu . Nếu mẫu phù hợp với một số tệp, nó sẽ được thay thế bằng danh sách tên tệp phù hợp, nếu không nó sẽ được để lại một mình.

Ví dụ, giả sử rằng biến foochứa a* b* c*và thư mục hiện hành chứa các tập tin bar, bazpaz. Sau đó ${foo#??}được mở rộng như sau:

  1. Giá trị của biến là chuỗi 8 ký tự a* b* c*.
  2. #??nghĩa là loại bỏ hai ký tự đầu tiên, dẫn đến chuỗi 6 ký tự  b* c*(có khoảng trắng ban đầu).
  3. Nếu việc mở rộng nằm trong ngữ cảnh danh sách (nghĩa là không có dấu ngoặc kép hoặc ngữ cảnh tương tự khác), hãy tiếp tục.
  4. Chia chuỗi thành các từ được phân tách bằng khoảng trắng, dẫn đến một danh sách gồm hai chuỗi: b*c*.
  5. Chuỗi b*, được hiểu là một mẫu, khớp với hai tệp: barbaz. Chuỗi c*phù hợp với không có tập tin vì vậy nó được để lại một mình. Kết quả là một danh sách ba dây: bar, baz, c*.

Ví dụ echo ${foo#??}in bar baz c*(lệnh echotham gia các đối số của nó với khoảng trắng ở giữa).

Để biết thêm chi tiết, xem:


2
Lưu ý rằng nó được gọi là mở rộng tham số vì nó áp dụng cho các biến ( $var) các loại thông số thích $1, $#, $?, $-...
Stéphane Chazelas

12

toàn cầu / chia

Tôi sẽ lấy toàn cầu / chia trước. Câu trả lời của @ Stephane mà bạn liên kết đến là sử dụng các thuật ngữ đó theo nghĩa chung. Chúng không phải là các lệnh thực tế hoặc bất cứ thứ gì tương tự, chỉ là các thao tác giả.

Việc split("$test")này sẽ chia nội dung của "$ test" thành một "mảng" các phần tử.

Sau glob(...)đó, sẽ cẩn thận để mở rộng bất kỳ yếu tố nào trong số này có chứa các ký tự toàn cầu vỏ như *hoặc phạm vi [1-2].

Thí dụ

Nói chuỗi của chúng tôi $testlà như sau.

$ test="afile[1-2] afile[3-5]"

Ngoài ra, hãy nói rằng chúng tôi có một thư mục với một số tệp trong đó.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Bây giờ nếu chúng tôi cố gắng lặp lại nó mà không có dấu ngoặc kép, bạn sẽ nhận thấy rằng chuỗi của chúng tôi đã bị tách ra trên các khoảng trắng, và sau đó bất kỳ ký tự toàn cầu nào cũng được mở rộng.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Tuy nhiên nếu chúng ta trích dẫn biến khi chúng ta chuyển nó làm đối số echothì chúng ta sẽ có được chuỗi ký tự gốc.

$ echo "$test"
afile[1-2] afile[3-5]

mở rộng biến

Thuật ngữ mở rộng biến có nghĩa là bao trùm hoạt động cơ bản mà shell đang thực hiện như là một phần của hoạt động cơ bản. Shell chịu trách nhiệm phân tích cú pháp đầu vào và sau đó thực hiện đầu vào này một khi nó được coi là đúng về mặt cú pháp.

Trong ví dụ trước của chúng tôi. Khi biến $testđược trình bày để không echotrích dẫn, chúng tôi đã nói với trình bao đi trước và phân tách các đối số đó và sau đó đưa chúng vào.

Khi được trích dẫn, về cơ bản, chúng tôi đã vô hiệu hóa tính năng đó với (các) biến chúng tôi đã bao bọc bằng dấu ngoặc kép.

Thí dụ

Dưới đây là một số ví dụ bổ sung về việc tách và tách.

toàn cầu / chia tách xảy ra tự động

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

toàn cầu / tách bị vô hiệu hóa thông qua trích dẫn kép

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}

Tôi không biết phạm vi cũng làm việc theo thứ tự ngược lại.
Joe
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.