Önceki komutun son argümanı nedir?


12

$_ önceki komutun son argümanı olduğu söylenir.

Acaba neden değil EDITOR="emacs -nw"ama EDITORaşağıdaki örnekte?

Neden "emacs -nw"son argümanın bir parçası değil ?

Daha genel olarak, bir argümanın ve son argümanın tanımları nelerdir?

Teşekkürler.

$ export EDITOR="emacs -nw"
$ echo $_
EDITOR

3
Sanırım shellcheck, değişkenleri atadığınız aynı satıra aktarmamanızı söylüyor. Atama gerçekleşir ve ardından değişken dışa aktarılır. EDITORihracat için bir argüman
jesse_b

FWIW pdkshve dashatanan değeri içerecek, ancak ksh93olduğu gibi davranacaktır bash.
Kusalananda

zsh:, export FOO=bar; echo $_yazdırır export.
ilkkachu

@Jesse_b Her şey son argüman / işlenen (atanan değer dahil), ancak exportyerleşik bir yardımcı program ile ilgili bir şey olabilir .
Kusalananda

ksh: typeset -x FOO=barsonra echo $_yazdırır FOO, ancak Bash declare -x FOO=bar; echo $_yazdırır FOO=bar.
ilkkachu

Yanıtlar:


13

Bash (ile onlar argüman olarak izin yaparken, değişken atamaları işler alias, declare, export, local, readonly, ve typeset), her şeyden önce (- genleşme değişkenlere atanan değerler için geçerlidir doğrusu, bu her şeyden önce onları tanımlar). O kelime genişleme aldığında, kalan komut edilir export EDITOR, böylece _olarak ayarlanır EDITOR.

Genel olarak konuşursak, argümanlar genişlemeden sonra kalan "kelimeler" dir (değişken atamaları ve yönlendirmeleri içermez).

Ayrıntılar için Bash kılavuzundaki Basit komut genişletme bölümüne bakın .


Ve declaredavranışlarının tanımladığımla eşleşmediğinin farkındayım ...
Stephen Kitt

Bu konuda pek tutarlı değil. declare a=b; echo $_baskılar a=b; export c=d; echo $_sadece yazdırır c. Öte yandan alias, sadece adı localyazdırırken, tüm argümanı yazdırır. Ayrıca readonly, düşündüğüm readonlyve localbenzer olacağımdan beri biraz şaşırtıcı bulduğum adı da yazdırıyor declare.
ilkkachu

1
@ilkkachu heh, bunu ben de fark ettim (yukarıya bakınız). exportve readonlybirlikte ilan edilir setattr.def, declare, local, ve typesetilan edilir declare.def, aliastek başına kalmıştır alias.def.
Stephen Kitt

Teşekkürler. Değişken atamaları bazı komutlara bağımsız değişken olarak kullanıldığında, (1) "(ya da daha doğrusu, bunları herhangi bir şeyden önce tanımlar - genişletme, değişkenlere atanan değerlere uygulanır)", değişken ataması gerçekleştirilmeden önce değerlere genişleme olur mu? (2) "Sözcük genişletmeye geldiğinde, kalan komut dışa aktarma EDİTÖRÜ" demek, genişletme işleminden önce değişken atama gerçekleştirme anlamına mı geliyor? İki alıntı birbiriyle çelişiyor gibi görünüyor.
Tim

Teşekkürler. Biraz kafam karıştı. Değişken atamalarının argümanları olarak kullanıldığında alias, declare, export, local, readonlyve typeset. Önce ve sonra ne olacak? "Kelime genişletmeye geldiğinde, kalan komut export EDITOR", değişken atamasının EDITOR="emacs -nw"genişletmeden önce gerçekleştiğini ima ediyor musunuz? Değilse, kalan komut neden ödevi bağımsız değişken olarak içermiyor? Evetse, değişken atamasını gerçekleştirmeden önce değişkenlere atanan değerlerin genişletilmesi gerekmez mi?
Tim

4

TL; DR: export FOO=barBash, geçici ortam yaratımını başlatır, FOO=baro ortamda ayarlanır , sonra son komutunu verir export FOO. Bu noktada, FOOson argüman olarak ele alınır.


Ah, çok istismar edilmiş $_:

($ _, alt çizgi.) Kabuk başlangıcında, ortam veya bağımsız değişken listesinde geçirildiği sırada yürütülen kabuk veya kabuk komut dosyasını çağırmak için kullanılan mutlak yol adına ayarlayın. Daha sonra, genişletmeden sonra önceki komutun son bağımsız değişkenine genişler. Ayrıca, bu komuta aktarılan ortama yürütülen ve yerleştirilen her komutu çağırmak için kullanılan tam yol adına ayarlanır. Postaları kontrol ederken, bu parametre posta dosyasının adını tutar.

Birkaç varyasyona bakalım:

$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_

echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_

$ export MANPATH=/tmp; echo $_
MANPATH

Burada üç model görüyoruz:

  • Dosya sistemi, işlevler ve yerleşik öğelerden çağrılan komutlar genellikle beklendiği gibi davranır: $_bağımsız değişken yoksa komut adının kendisine ayarlanır, aksi takdirde sunulan bağımsız değişkenlerin sonuncusu.
  • İşlev tanımlarından, döngülerden ve diğer mantıksal yapılardan sonra: $_değiştirilmez.
  • Diğer her şey: $_tam olarak beklenmeyen bir şeye ayarlanmıştır; tuhaf.

Ben kod gariplik hakkında bir fikir sağlamak için kullandım.

$ ./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$ ./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$ ./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]

Ayrıştırıcınınlastarg= tüm durumlarda beklenen son argümanı ( ) gördüğünü görebilirsiniz , ancak bundan sonra ne olacağı, bash'ın ne olacağını düşünmesine bağlıdır. Bkz. Execute_cmd.c, execute_simple_command () .

Durumunda export FOO=barbash atamayı yapar ve sonra değişkeni dışa aktarır. Bu, belgelerin genişlemeden sonra hesaplanan son argümanın iddialarıyla tutarlı görünmektedir.


1
Kabuk postayı kontrol ettiğinizi nasıl biliyor?
rackandboneman

@rackandboneman onaylamadan, iç kontrollere dayanarak yapıldığından şüpheleniyorumMAILCHECK
Jeff Schaller

2

Başlık sorusunu cevaplamak için şunu deneyin !$:

$ export EDITOR="emacs -nw"
$ echo !$
EDITOR=emacs -nw

Bu tarih genişlemesi. Bash manpage'den:

Geçmiş genişlemesi, tam bir satır okunduktan hemen sonra, kabuk kelimelere bölünmeden önce gerçekleştirilir. İki kısımda gerçekleşir. Birincisi, değişiklik listesinden geçmiş listesinden hangi satırı kullanacağını belirlemektir. İkincisi, geçerli çizgiye dahil edilmek üzere o çizginin bölümlerini seçmektir. Geçmişten seçilen satır olaydır ve bu satırın üzerinde işlem yapılan kısımları kelimelerdir.

...

Etkinlik İşaretçileri

...

! Ardından boş, yeni satır, satır başı, = veya ((extglob kabuk seçeneği shopt yerleşiği kullanılarak etkinleştirildiğinde) dışında bir geçmiş değişikliği başlatın.

...

!! Önceki komuta bakın. Bu,!! -1 ile eşanlamlıdır.

...

Kelime İşaretçileri

...

$ Son söz. Bu genellikle son argümandır, ancak satırda yalnızca bir kelime varsa sıfırıncı kelimeye genişler.

...

Olay belirtimi olmadan bir sözcük belirleyici sağlanırsa, olay olarak önceki komut kullanılır.


Waaaaay sorunun başlığını tam anlamıyla alıyorsunuz. (Tamam, kötü bir başlık.) Hepimiz görebiliyoruz ki « export EDITOR="emacs -nw"» komutu iki kelimeden oluşuyor: birincisi « export» ve ikincisi « EDITOR="emacs -nw"». Soru gerçekten soruyor: “Bash man sayfası ve Bash El Kitabı !_, bash bu durumda $_« EDITOR»olarak ayarlandığında,“ önceki komutun son argümanına genişler ” derken ne anlama geliyor ?” Bash man sayfası bölümünün geçmiş genişletme üzerine kopyalanması ve yapıştırılması özellikle yararlı değildir.
G-Man
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.