SORU
21 NİSAN 2014, PAZARTESİ


Bash betikleri için bir semantiği?

Daha başka bir dil biliyorum, "" küçük bir şeye ihtiyacım var her zaman Googling tarafından. Bash öğrendim Sonuç olarak, birlikte çalışmak için görünen küçük komut yamalı edebilirim. Ancak, bilmiyorumgerçektenneler olduğunu, ve daha resmi bir giriş için bir programlama dili olarak Bash için umuyordum. Değerlendirme sırası Nedir? örneğin: ne ölçüm kuralları? Yazmak disiplin, örneğin her bir dize nedir? Program -- devlet değişken adları; daha da fazlası var, mesela dizeleri anahtar-değer bir ödev yığını nedir? Bir öbek var mı? Ve benzeri.

Düşündüm bakın GNU Bash manuel için bu tür bir fikir, ama değil gibi görünüyor ne istiyorum; daha çok bir çamaşır listesi sözdizimsel şeker yerine bir açıklama çekirdek semantik modeli. Milyon-ve-bir "rehberler" online sadece daha kötü. bash Belki de ilk sh çalışma ve bunun üzerine sözdizimsel şeker gibi Bash anlamak gerekir? Eğer bu doğru bir model, ama bilmiyorum.

Herhangi bir öneriniz var mı?

DÜZENLEME:Ne aradığımı örnekleri sağlamak istendi. Bir düşünün ne çok uç bir örnek, bir "biçimsel anlambilim" this paper on "the essence of JavaScript". Belki biraz daha az resmi bir örnek Haskell 2010 report.

CEVAP
21 NİSAN 2014, PAZARTESİ


Bir kabuk işletim sistemi için bir arayüz. Genellikle özellikleri kolay özellikle işletim sistemi ve dosya sistemi ile etkileşim için yapmak için tasarlanmış kendi içinde, ama daha fazla veya daha az güçlü bir programlama dilidir. POSIX kabuk (anılacaktır gibi, "kabuk") semantiği vardır bir bit bir pire torbası, birleştiren bazı özellikleri LİSP (s-ifadeleri birçok yönümüz ortak kabuğu word splitting) ve C (çok kabuk arithmetic syntax anlambilim gelir C).

Kabuk sözdizimi diğer kök bireysel UNIX yarar bir karışıklık olarak yetişmesi geliyor. Sık sık kabuk yerleşiklere ne çoğu aslında dış komutlar olarak uygulanabilir. /bin/[ çoğu sistemde var olduğunu farkettiği bir döngü için birçok yeni kabuk atar.

$ if '/bin/[' -f '/bin/['; then echo t; fi # Tested as-is on OS X, without the `]`
t

wat?

Bu bir kabuk nasıl uygulanır bakarsanız çok daha mantıklı. İşte bir egzersiz olarak yaptığım bir uygulama. Python, ama herkes için bir mesele değil umarım. Çok güçlü değil, ama öğreticidir:

#!/usr/bin/env python

from __future__ import print_function
import os, sys

'''Hacky barebones shell.'''

try:
  input=raw_input
except NameError:
  pass

def main():
  while True:
    cmd = input('prompt> ')
    args = cmd.split()
    if not args:
      continue
    cpid = os.fork()
    if cpid == 0:
      # We're in a child process
      os.execl(args[0], *args)
    else:
      os.waitpid(cpid, 0)

if __name__ == '__main__':
  main()

Yukarıda bir kabuk yürütme modeli oldukça açık bir şekilde ifade eder umarım

1. Expand words.
2. Assume the first word is a command.
3. Execute that command with the following words as arguments.

Genişleme, komut çözünürlük, yürütme. Kabuk şimdi anlamları tüm yukarıda yazdığım uygulama daha çok daha zengin oldukları halde bu üç şey birine bağlı.

Tüm komutları fork. Aslında, orada bir avuç komutları zorlama a ton of sense uygulanan dışındakiler (gibi onlar-cekti var fork) ancak çoğu kez kullanılabilir gibi dışındakiler için sıkı POSIX uyumu.

Bash yeni özellikler ve anahtar kelimeler POSIX kabuk geliştirmek için ekleyerek bu temel üzerine inşa ediyor. Sh ile neredeyse uyumludur ve bash script bazı yazarlar yıl bir senaryo aslında POSİXly sıkı bir sistemde çalışmayabilir farkında olmadan öyle her yerde. (Ben de insanların bu kadar çok programlama dili ve semantiği için çok küçük ve kabuk stil semantik ve stil hakkında bakım nasıl merak ediyorum, ama ben sapmak.)

Değerlendirme sırası

Bu hileli bir soru oldu: Bash aritmetik sözdizimi soldan sağa, ama C öncelik izler. birincil sözdizimi ifadeleri yorumlar İfadeler farklıaçılımlarıama. Bash kullanma kılavuzu: EXPANSION bölümünden

Açılımları sırasıdır: ayraç genişleme; tilde genişleme, parametre ve değişken genişleme, genişleme aritmetik ve komut ikamesi (soldan sağa doğru bir şekilde yapılır); sözcük bölme; ve genişletme yol.

Eğer wordsplitting, yol genişletme ve parametre genişleme anlamak, iyi bash yaptığı en anlamak için yolda. Yol genişletme wordsplitting sonra gelecek adı boşluk içeren bir dosya hala bir topak ile uyumlu olmasını sağlar, çünkü çok önemlidir, unutmayın. Bu kısım açılımları iyi kullanmak genel olarak ** 67, daha iyi olmasıdır.

Kapsam

Kapsam fonksiyonu

Çok eski ECMA gibi, kabuk açıkça bir işlev içinde adlarını bildirin sürece dinamik bir kapsamı vardır.

$ foo() { echo $x; }
$ bar() { local x; echo $x; }
$ foo

$ bar

$ x=123
$ foo
123
$ bar

$ …

Ortamı ve süreci "" kapsam

Atom üst kabuklarının değişkenleri miras, ama işler başka türlü unexported adları miras yok.

$ x=123
$ ( echo $x )
123
$ bash -c 'echo $x'

$ export x
$ bash -c 'echo $x'
123
$ y=123 bash -c 'echo $y' # another way to transiently export a name
123

Bu kapsama kuralları birleştirir:

$ foo() {
>   local -x bar=123 # Export foo, but only in this scope
>   bash -c 'echo $bar'
> }
$ foo
123
$ echo $bar

$

Yazmak disiplin

Um, türleri. Evet. Bash gerçekten tip yok, ve her şey bir dize (veya belki de bir . genişler ^em>kelimedaha uygun olur.) Ama açılımları farklı türleri inceleyelim.

Dizeleri

Her şeyi bir dize olarak tedavi edilebilir. Bash Barewords tamamen genişleme uygulanan ilaçlara bağlı olan dizeler.

Hayır genişleme

Çıplak bir kelime sadece bir kelime olduğunu, ve tırnak bu konuda değişen bir şey olduğunu göstermek için yararlı olabilir.

$ echo foo
foo
$ 'echo' foo
foo
$ "echo" foo
foo
Alt genişleme
$ fail='echoes'
$ set -x # So we can see what's going on
$ "${fail:0:-2}" Hello World
  echo Hello World
Hello World

Açılımları hakkında daha fazla bilgi için El Kitabı Parameter Expansion bölümünü okuyun. Oldukça güçlü.

Tamsayılar ve aritmetik ifadeler

Kabuk aritmetik olarak atama ifadeleri sağda tedavisinde söylemek tamsayı öznitelik adları ile aşılamak. Parametre genişleyen önce tamsayı matematik olarak değerlendirilecektir genişlediğinde sonra, ... bir dize.

$ foo=10 10
$ echo $foo
10 10
$ declare -i foo
$ foo=$foo # Must re-evaluate the assignment
$ echo $foo
20
$ echo "${foo:0:1}" # Still just a string
2

Diziler

Bağımsız ve Konumsal Parametreler

Dizi hakkında konuşmadan önce değer konum parametreleri tartışıyor olabilir. Bir kabuk bağımsız erişilen sayılı parametreleri, $1, $2, $3, vb kullanarak olabilir. Bir zamanlar dizileri ile çok ortak noktası olan "$@" kullanarak tüm bu parametreler erişebilirsiniz. Ve konumsal parametreler set shift yerleşiklere kullanarak, ya da sadece kabuk ya da bu parametreler ile bir kabuk işlevi çağırarak değiştirebilirsiniz:

$ bash -c 'for ((i=1;i<=$#;i  )); do
>   printf "\$%d => %s\n" "$i" "${@:i:1}"
> done' -- foo bar baz
$1 => foo
$2 => bar
$3 => baz
$ showpp() {
>   local i
>   for ((i=1;i<=$#;i  )); do
>     printf '$%d => %s\n' "$i" "${@:i:1}"
>   done
> }
$ showpp foo bar baz
$1 => foo
$2 => bar
$3 => baz
$ showshift() {
>   shift 3
>   showpp "$@"
> }
$ showshift foo bar baz biz quux xyzzy
$1 => biz
$2 => quux
$3 => xyzzy

Bash manuel de bazen konumsal parametre olarak $0 anlamına gelir. Bu argüman ancak sayılı bir parametredir $#, çok vıdı sayısı dahil değil çünkü bu kafa karıştırıcı buluyorum. $0 kabuk adı ya da geçerli bir kabuk programı.

Diziler

Diziler sözdizimi konumsal parametreler modellenmiş, çoğunlukla sağlıklı adında bir dizi sanırım bu yüzden "harici konumsal parametreler, eğer istersen.", Diziler aşağıdaki yaklaşımlar kullanılarak bildirilebilir:

$ foo=( element0 element1 element2 )
$ bar[3]=element3
$ baz=( [12]=element12 [0]=element0 )

Dizin tarafından bir dizi öğelerini erişebilirsiniz:

$ echo "${foo[1]}"
element1

Diziler dilim

$ printf '"%s"\n' "${foo[@]:1}"
"element1"
"element2"

Eğer normal bir dizi parametre olarak ele alırsanız, Sıfırıncı indeks alırsınız.

$ echo "$baz"
element0
$ echo "$bar" # Even if the zeroth index isn't set

$ …

Eğer tırnak ya da ters wordsplitting önlemek için kullanırsanız, dizi belirtilen wordsplitting korur:

$ foo=( 'elementa b c' 'd e f' )
$ echo "${#foo[@]}"
2

Diziler ve konumsal parametreler arasındaki temel fark vardır:

  1. Konumsal parametreler yok denecek kadar azdır. Eğer $12 ayarlanmışsa, $11 ayarlanmış olduğundan emin olabiliriz. (Boş dize, ama $# 12. daha küçük olmayacak) ayarlanmış olabilir Eğer "${arr[12]}" ayarlanmışsa, "${arr[11]}" belirlenen garanti yok, ve dizi uzunluğu 1 kadar küçük olabilir.
  2. Bir dizinin Sıfırıncı elemanı olmadığını açıkça gösteren bir dizinin Sıfırıncı elemandır. Konumsal parametreler, Sıfırıncı öğesi değililk bağımsız değişkenama kabuk ya da kabuk adı.
  3. shift dizisi, dilim ve yeniden atama için, arr=( "${arr[@]:1}" ) gibi. Ayrıca unset arr[0], yapabilirsin ama o dizin 1'deki ilk eleman olur.
  4. Diziler bütünsel olarak örtülü olarak kabuk işlevleri arasında paylaşılabilir, ama onları görmek için açıkça bir kabuk işlevi için konumsal parametreleri geçirmek için var.

Genellikle kolay yol genişletme adlarını dizileri oluşturmak için kullanılır

$ dirs=( */ )

Komutlar

Komutları anahtarı vardır, ama aynı zamanda manuel tarafından daha derinlemesine kaplılar. SHELL GRAMMAR bölümünü okuyun. Komutları farklı türü vardır:

  1. Basit Komutları (örneğin $ startx)
  2. Boru hatları ($ yes | make config gibi) (lol)
  3. Listeler (örneğin $ grep -qF foo file && sed 's/foo/bar/' file > newfile)
  4. Bileşik Komutları (*59 örneğin*)
  5. Coprocesses (Karmaşık, hiçbir örnek)
  6. Fonksiyonlar (basit bir komut olarak ele alınabilir adlı Bir bileşik komut)

Yürütme Modeli

Elbette yürütme modeli, bir öbek ve bir iki yığın içerir. Bu tüm UNIX programları için endemik. Bash da bir ara kabuk işlevleri için yığın caller yerleşik iç içe kullanımı ile görülebilir.

Referanslar:

  1. Bash manuel SHELL GRAMMAR bölümü
  2. XCU Shell Command Language belgeleri
  3. Greycat. wiki Bash Guide.
  4. Advanced Programming in the UNIX Environment

Eğer beni daha belirli bir yönde genişletmek isterseniz yorum yapın lütfen.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BroadCity

    BroadCity

    10 ŞUBAT 2010
  • David MeShow

    David MeShow

    10 EKİM 2006
  • We've moved!

    We've moved!

    7 Ocak 2008