Giải quyết tất cả các bí danh trong một dòng lệnh zsh


12

Tôi đã đặt các bí danh lồng nhau và tôi muốn giải quyết tất cả chúng trước khi thực hiện lệnh. Làm thế nào để làm điều đó?

Nếu có một chức năng không bị ràng buộc với bất kỳ phím nào thì M-x foobartôi cũng ổn. Tôi thậm chí có thể sử dụng lệnh bên ngoài ( type, command, which, bất cứ điều gì). Tôi đã thử mọi thứ từ chuỗi Tại sao không sử dụng "which"? Dùng gì rồi? nhưng không có gì hoạt động.


2
C-x amở rộng bí danh dưới con trỏ (giả sử bạn đang sử dụng hệ thống hoàn thành).
Stéphane Chazelas

Phải , _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Điều đó rất hữu ích, tuy nhiên điều đáng tiếc là trong bash người ta có thể mở rộng toàn bộ dòng nhưng trong zsh thì không.
WeSenseASoulInSearchOfAnswers

Tôi cho rằng có thể viết một lệnh ràng buộc mà gọi _expand_aliascho đến khi bộ đệm chỉnh sửa không còn thay đổi.
vinc17

Câu trả lời:


10

Lưu ý rằng Ctrl-Alt-E bashkhông chỉ mở rộng bí danh. Nó cũng mở rộng các biến, thay thế lệnh (!), Thay thế quá trình (!), Mở rộng số học và xóa các trích dẫn (nó không tạo ra tên tệp (globalbing) hoặc mở rộng dấu ngã).

Nó không luôn luôn quản lý để mở rộng bí danh. Vì vậy, trong khi nó có công dụng, điều quan trọng là nhận ra kết quả của nó có khả năng thay đổi ý nghĩa của dòng lệnh, có tác dụng phụ và có khả năng nguy hiểm.

Ví dụ:

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done

Nếu tôi nhấn M-C-Evào đây, điều đó mang lại cho tôi:

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done

Điều này mang lại cho tôi một dòng lệnh hoàn toàn khác nhau (và tưởng tượng những gì sẽ xảy ra nếu tôi có rm -rf *thay vì pwdở trên) và không mở rộng foobí danh.

Với zsh, để xây dựng ghi chú của Gilles về các bí danh được mở rộng bên trong các chức năng, bạn có thể làm:

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases

Điều đó sẽ mở rộng các bí danh chỉ khi dòng lệnh hiện tại có hiệu lực về mặt cú pháp (vì vậy nó sẽ tăng gấp đôi như một trình kiểm tra cú pháp).

Trái ngược với bashMCE, nó cũng giải quyết hoàn toàn các bí danh. Ví dụ: nếu bạn có:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll

Sẽ được mở rộng thành:

$ ls --color -l

Lưu ý rằng nó cũng chuẩn hóa cú pháp để những thứ như:

$ for i (*) cmd $i; foo

sẽ được đổi thành:

$ for i in *
        do
                cmd $i
        done
        foo

Đây là lỗi. Nếu tôi có alias ls='ls --color'và gõ C-x aqua ls, tôi nhận được: \ls --color(do đó mới lskhông hiểu sai như một bí danh). Nhưng với bạn expand-aliases, tôi nhận được : ls --color, làm cho kết quả mơ hồ.
vinc17

@ vinc17, nó không mơ hồ ở chỗ nó giải quyết hoàn toàn bí danh (về mặt đó, nó ít lỗi hơn so với bashtương đương). Nhưng đó là sự thật nếu bạn chạy lệnh sau đó, bạn sẽ nhận được một vòng mở rộng bí danh khác (như trong bash), vì vậy lý tưởng nhất là bạn muốn tạm thời vô hiệu hóa mở rộng bí danh, ví dụ như bọc nó trong một (){ setopt localoptions noexpandalias; ...; }. Lưu ý rằng bạn có thể nói _expand_aliaslà lỗi cũng như nó mở rộng bí danh khi chạy trên \ls.
Stéphane Chazelas

@ vinc17, dấu gạch chéo ngược thoát được thực hiện bởi _expand_aliascũng dễ bị lừa như alias 'foo=repeat 3 foo'hay alias ls='ls --color'; alias '\ls=echo fooled'. Không có giải pháp hoàn hảo ở đây.
Stéphane Chazelas

Về _expand_aliascho alias 'foo=repeat 3 foo', tôi sẽ coi xuyệc ngược thiếu như một lỗi. Và alias '\ls=echo fooled'không nên cho phép; Ở đây tôi thích bash, trong đó nói : bash: alias: '\ls': invalid alias name.
vinc17

@ vinc17, tôi không thể thấy làm thế nào có thể được coi là bất cứ điều gì khác ngoài một hạn chế trong bash. Nếu bạn không thích bí danh với dấu gạch chéo ngược, đừng sử dụng chúng, nhưng tại sao bạn lại muốn vỏ từ chối chúng? Mặc dù bí danh là chức năng thay thế chức năng của một người đàn ông nghèo trong csh (nơi họ đến), trong các vỏ giống như Bourne, họ là những kẻ hack để thực hiện các thủ thuật không thể thực hiện được với các chức năng, một số hình thức mở rộng macro nối sớm trong trình phân tích cú pháp trình bao , Tôi không thấy điểm nào trong việc hạn chế những gì nó có thể làm.
Stéphane Chazelas

6

Nếu bạn nhét một dòng lệnh vào một định nghĩa hàm và sau đó in ra hàm, các bí danh sẽ được mở rộng. Bạn cũng sẽ có được khoảng trắng bình thường.

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}

Để đặt tất cả điều này vào một lệnh tương tác, bạn có thể tạo một tiện ích zle. Bạn có thể định nghĩa một hàm trực tiếp bằng cách nhồi mã của nó vào một mục trong functionsmảng; bạn sẽ nhận được hiệu ứng chuẩn hóa khi bạn đọc lại.

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey  normalize-command-line

Bạn có được hiệu ứng chuẩn hóa tương tự trong preexechook . Các bí danh cũng được mở rộng tại thời điểm một chức năng được tự động tải ( autoload -Uthường được sử dụng để tránh mở rộng bí danh).

Hàm _expand_aliashoàn thành sẽ mở rộng từ dưới con trỏ nếu đó là bí danh. Nó sử dụng aliasesmảng . Nó không phải là đệ quy. Bạn có thể thực hiện mở rộng bí danh chung hơn bằng cách sử dụng aliases, nhưng điều này hơi khó, vì tìm ra các vị trí mà bí danh được mở rộng được kết nối mật thiết với cú pháp shell.


2
Tôi luôn luôn sử dụng autoload -Uđơn giản vì tài liệu zsh đề xuất nó, nhưng tôi không bao giờ hiểu những gì -Uthực sự đã làm cho đến khi tôi đọc nó :). Ngoài ra cho bất cứ ai quan tâm, người ta có thể gọi _expand_alias chức năng trực tiếp bằng cách gõ bí danh của bạn vào dòng lệnh, đánh <Esc>, x, để khởi động minibuffer, sau đó gõ_expand_alias<Enter>
the_velour_fog

2

Nếu bạn có nhiều bí danh lạ mắt lồng nhau và bạn không chắc zsh thực sự đang làm gì với chúng và trong đó các tùy chọn thứ tự được truyền cho lệnh thì bạn luôn có thể bắt đầu zsh với -xtùy chọn. Điều này sẽ in các lệnh và đối số khi chúng được thực thi.

Tuy nhiên, hãy lưu ý rằng tùy chọn này được dùng cho mục đích gỡ lỗi, vì vậy nó sẽ in rất nhiều thứ vô dụng ngay sau khi zsh -xgọi (về cơ bản mỗi chức năng / widget / plugin của .zshrc của bạn) và trong khi thực thi lệnh, nó cũng có thể dài dòng nếu bạn đã xác định preexecprecmdhook.

Tôi cũng nên đề cập rằng, nó chỉ in những lệnh cuối cùng được thực thi và các lệnh riêng biệt được in riêng biệt để sau đó

alias a='echo a'
alias b='echo b'
alias c='echo c'
alias d='echo d'
a && b || c; d

Bạn sẽ thấy

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
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.