Ý nghĩa của món ăn _ = là gì?


29

Sau khi tôi chạy set -a var=99, tôi có thể tìm thấy một câu trong đầu ra của set:

...
TERM=xterm
UID=0
USER=root
VIRTUAL_ENV_DISABLE_PROMPT=1
_=var=99
colors=/etc/DIR_COLORS
...

Ai đó có thể cho tôi biết "_ =" nghĩa là gì không?

Tôi lưu ý rằng echo $varsẽ không có gì. Nếu tôi chạy set -a, thì setsẽ không bao gồm biến này nữa. Chuyện gì đang xảy ra vậy?


Câu trả lời:


16

Khi bạn thực thi set -a var=99, có ba điều khác biệt xảy ra (liên quan đến câu hỏi của bạn):

  1. Một tùy chọn thiết lập ( -a) (đảo ngược bằng cách thực hiện set +a) để xuất vars.
  2. Các tham số vị trí được "đặt" thành những gì theo sau các tùy chọn ( $1được đặt thành var=99).
  3. Dấu gạch dưới biến shell $_được đặt thành tham số cuối cùng (mở rộng).

đặt -a

Việc thực hiện set -ađánh dấu tất cả các biến tiếp theo (mới hoặc thay đổi) là xuất (trong tất cả các shell, ngoại trừ cshvà một số shell liên quan).

$ set -a
$ myvariable=wer
$ env | grep myvariable
myvariable=wer

Để khắc phục thiết lập này, chỉ cần thay đổi -một +:

$ set +a
$ unset myvariable              # to erase it from the environment if it
                                # was exported before the change of set +a
$ myvariable=456544654          # A new value of the variable.
$ env | grep "variable"         # No output means the var does not exist
                                # in the current environment

đặt var = 99

Điều này thực sự nên set -- var=99tránh để giải thích một tùy chọn (và tập hợp có rất nhiều) với các giá trị bắt đầu bằng dấu gạch ngang ( -).

Đặt danh sách các đối số (danh sách các tham số vị trí) thành sau đó --. Điều đó là hợp lệ trong tất cả các shell hợp lý (không phải trong csh et al). Đối số vị trí được in bằng "$ @" (hoặc "$ *" tương tự, không bằng nhau).

$ set -- a=1 b=2 c=3
$ echo "$@"
a=1 b=2 c=3

_ = last_argument

Và, giá trị của biến shell bên trong _thay đổi thành đối số cuối cùng của dòng được thực thi. Điều đó KHÔNG đúng trong hầu hết tất cả các shell (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh và tất nhiên là csh và tcsh) trừ bash.

$ echo one two last argument
one two last argument

$ echo "$_"
argument

$ echo This is a new: last_argument
This is a new: last_argument

$ echo "$_"
last_argument

Xin lưu ý rằng giá trị trong $_là giá trị sau khi mở rộng:

$ a="A New_Argument"
$ echo Something else to test: "$a"
Something else to test: A New_Argument

$ echo "$_"
A New_Argument

Đó là lý do tại sao khi bạn thực thi:

$ set -a myvar=99; set | grep 'myvar'
_=myvar=99

Bạn nhận được một mô tả về biến shell '$ _'. Điều này cũng hoạt động:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"

37

Gạch dưới thực sự là một biến shell đặc biệt. Những gì bạn đang thấy ở đây là biến gạch dưới ( _) với giá trị là var=99. Nó chỉ đọc và được duy trì bởi vỏ. Nó là:

  • Đặt khi khởi động shell, chứa tên tệp tuyệt đối của shell hoặc tập lệnh đang được thực thi như được chuyển trong danh sách đối số.
  • Sau đó, nó mở rộng đến đối số cuối cùng cho lệnh trước đó, sau khi mở rộng.
  • Khi kiểm tra thư, tham số này giữ tên của tệp thư.
  • Nó cũng được đặt thành tên đường dẫn đầy đủ của mỗi lệnh được thực thi và được đặt trong môi trường được xuất sang lệnh đó.

Ví dụ của bạn rơi vào loại thứ hai. Bạn đã gõ:

set -a var=99  

Vì vậy, đối số cuối cùng đã có var=99, và đó là giá trị bạn đang đặt (bạn không đặt varthành 99). Do đó, _đã được thiết lập để đó. Và đó là những gì đang được báo cáo:

_=var=99  

Hơi khó hiểu một chút, nhưng cái đầu tiên =biểu thị việc gán cho biến _và cái thứ hai là một phần của giá trị.

Điều đáng nói là -atùy chọn setnày sẽ khiến tất cả các biến được xác định sau đó được xuất ra.


16

Câu trả lời đúng sẽ phụ thuộc vào trình bao bạn đang sử dụng:

  • cho bashbất cứ điều gì @BobEager nói áp dụng
  • zsh, nó chỉ được đặt thành đối số cuối cùng của lệnh trước đó và thành tên đường dẫn đầy đủ của lệnh trong môi trường của lệnh
  • Một số shell như dashchỉ đặt biến này khi chạy phiên tương tác

Có thể có những đặc điểm khác trong vỏ khác. Như vậy, $_không được định nghĩa trong POSIX, vì vậy người ta cần phải nhận thức các vấn đề di tiềm năng khi sử dụng nó.

Lưu ý bên lề: nếu ý định của bạn là gán giá trị 99 varvà làm cho nó có sẵn trong môi trường của các quy trình con tiếp theo, cú pháp chính xác để đạt được điều này là:

export var=99

2
Một cú pháp cũng đúng là unset var;set -a; var=99. Hoạt động trong tất cả các vỏ có thể cộng hưởng (không phải csh et al).
Mũi tên

1
@Arrow Mặc dù theo dòng cuối cùng của câu trả lời của Bob Eag, điều này sẽ làm cho tất cả các biến sau đó được đặt / sửa đổi được xuất, có thể không phải là điều bạn muốn.
TripeHound

8

Và tôi lưu ý echo $varsẽ không có gì. Có chuyện gì vậy?

Trong bản in không đẹp của bash (1) , chúng tôi tìm thấy

set[ --abefhkmnptuvxBCEHPT] [ tên tùy chọn ] [ argồ ]   [ ] [ tên tùy chọn ] [ arg ]-o
set+abefhkmnptuvxBCEHPT+o

            ︙
    Khi tùy chọn được chỉ định, họ thiết lập hoặc thuộc tính vỏ unset. Bất kỳ đối số còn lại sau khi xử lý tùy chọn được coi là giá trị cho các tham số vị trí và được phân công, theo thứ tự, để $1, $2... .$n

Có nghĩa là, set -a var=99không đặt biến môi trường varthành 99; nó đặt $1thành var=99. Hãy thử echo "$1"hoặc echo "$*"và bạn sẽ thấy.

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.