Shell berorientasi objek untuk * nix


38

Pendahuluan: Saya suka bash dan tidak punya niat memulai segala jenis argumen atau perang suci, dan mudah-mudahan ini bukan pertanyaan yang sangat naif.

Pertanyaan ini agak terkait dengan posting ini pada pengguna super, tapi saya tidak berpikir OP benar-benar tahu apa yang dia minta. Saya menggunakan bash di FreeBSD, linux, OS X, dan cygwin di Windows. Saya juga memiliki pengalaman luas baru-baru ini dengan PowerShell di Windows.

Apakah ada shell untuk * nix, sudah tersedia atau dalam karya-karya, yang kompatibel dengan bash tetapi menambahkan lapisan skrip berorientasi objek ke dalam campuran? Satu-satunya hal yang saya tahu yang mendekati adalah konsol python, tetapi sejauh yang saya tahu itu tidak memberikan akses ke lingkungan shell standar. Misalnya, saya tidak bisa adil cd ~dan ls, kemudian chmod +x filedi dalam konsol python. Saya harus menggunakan python untuk melakukan tugas-tugas itu daripada binari unix standar, atau memanggil binari menggunakan kode python.

Apakah shell semacam itu ada?


3
Ada Pash tapi itu jauh lebih seperti Powershell daripada Bash.
ephemient

1
@ ememient mungkin Anda harus menulis jawaban untuk pash ... meskipun saya tidak tahu apa-apa, iirc, PowerShell adalah shell OO.
xenoterracide

4
Hei, Anda harus memeriksa ipython . Jika Anda memasukkan ekspresi yang tidak masuk akal sebagai python, itu akan mencoba memetakannya ke perintah shell. Misalnya, hal-hal seperti cd ~diikuti oleh lskarya seperti di Bash. Anda juga dapat menetapkan output ke variabel Python (daftar baris.. Semacam) dengan perintah seperti listing = !ls.
intuited

@intuited: mengagumkan, saya akan memeriksanya
Robert S Ciaccio

1
@intuited: iPython cukup bagus untuk hal-hal yang ingin saya lakukan, terima kasih!
Robert S Ciaccio

Jawaban:


43

Saya dapat memikirkan tiga fitur yang diinginkan dalam sebuah shell:

  • Kegunaan interaktif: perintah umum harus cepat untuk mengetik; penyelesaian; ...
  • Pemrograman: struktur data; konkurensi (pekerjaan, pipa, ...); ...
  • Akses sistem: bekerja dengan file, proses, windows, database, konfigurasi sistem, ...

Kerang Unix cenderung berkonsentrasi pada aspek interaktif dan mensubkontrakkan sebagian besar akses sistem dan beberapa pemrograman ke alat eksternal, seperti:

  • bc untuk matematika sederhana
  • openssl untuk kriptografi
  • sed , awk , dan lainnya untuk pemrosesan teks
  • nc untuk jaringan TCP / IP dasar
  • ftp untuk FTP
  • mail, Mail, mailx, Dll untuk e-mail dasar
  • cron untuk tugas yang dijadwalkan
  • wmctrl untuk manipulasi jendela X dasar
  • dcop untuk perpustakaan KDE ≤3.x
  • alat dbus ( dbus-*atau qdbus ) untuk berbagai informasi sistem dan tugas konfigurasi (termasuk lingkungan desktop modern seperti KDE ≥4)

Banyak, banyak hal dapat dilakukan dengan menjalankan perintah dengan argumen yang benar atau input yang disalurkan. Ini adalah pendekatan yang sangat kuat - lebih baik memiliki satu alat per tugas yang melakukannya dengan baik, daripada satu program yang melakukan semuanya dengan sangat buruk - tetapi ia memiliki keterbatasan.

Keterbatasan utama shell unix, dan saya menduga inilah yang Anda cari dengan persyaratan "scripting berorientasi objek" Anda, adalah bahwa mereka tidak pandai menyimpan informasi dari satu perintah ke perintah berikutnya, atau menggabungkan perintah dengan cara yang lebih bagus daripada sebuah pipa. Secara khusus, komunikasi antar-program berbasiskan teks, sehingga aplikasi hanya dapat digabungkan jika mem-serialkan datanya dengan cara yang kompatibel. Ini adalah berkah sekaligus kutukan: pendekatan segalanya-teks-membuatnya mudah untuk menyelesaikan tugas-tugas sederhana dengan cepat, tetapi meningkatkan penghalang untuk tugas-tugas yang lebih kompleks.

Kegunaan interaktif juga berjalan agak terhadap pemeliharaan program. Program interaktif harus pendek, membutuhkan sedikit penawaran, tidak mengganggu Anda dengan deklarasi variabel atau mengetik, dll. Program yang dapat dipertahankan harus dapat dibaca (jadi tidak memiliki banyak singkatan), harus dapat dibaca (sehingga Anda tidak perlu bertanya-tanya apakah kata yang telanjang) adalah string, nama fungsi, nama variabel, dll.), harus memiliki pemeriksaan konsistensi seperti deklarasi variabel dan pengetikan, dll.

Singkatnya, shell adalah kompromi yang sulit untuk dicapai. Ok, ini mengakhiri bagian kata-kata kasar, ke contoh.


  • The Perl Shell (psh) “menggabungkan sifat interaktif dari Unix shell dengan kekuatan Perl”. Perintah sederhana (bahkan jaringan pipa) dapat dimasukkan dalam sintaks shell; yang lainnya adalah Perl. Proyek ini sudah lama tidak dikembangkan. Ini dapat digunakan, tetapi belum mencapai titik di mana saya akan mempertimbangkan menggunakannya di atas Perl murni (untuk skrip) atau shell murni (secara interaktif atau untuk skrip).

  • IPython adalah konsol Python interaktif yang ditingkatkan, terutama ditargetkan pada komputasi numerik dan paralel. Ini adalah proyek yang relatif muda.

  • irb (ruby interaktif) adalah setara dengan Ruby dari konsol Python.

  • scsh adalah implementasi skema (yaitu bahasa pemrograman yang layak) dengan jenis binding sistem yang secara tradisional ditemukan di shell unix (string, proses, file). Itu tidak bertujuan untuk dapat digunakan sebagai shell interaktif.

  • zsh adalah shell interaktif yang ditingkatkan. Intinya adalah interaktivitas (edisi baris perintah, penyelesaian, tugas-tugas umum diselesaikan dengan sintaks singkat tetapi samar). Fitur pemrogramannya tidak begitu bagus (setara dengan ksh), tetapi ia hadir dengan sejumlah perpustakaan untuk kontrol terminal, regexps, jaringan, dll.

  • ikan adalah awal yang bersih di shell unix-style. Tidak memiliki fitur pemrograman atau akses sistem yang lebih baik. Karena itu merusak kompatibilitas dengan sh, ia memiliki lebih banyak ruang untuk mengembangkan fitur yang lebih baik, tetapi itu belum terjadi.


Tambahan: bagian lain dari kotak alat unix memperlakukan banyak hal sebagai file:

  • Sebagian besar perangkat keras dapat diakses sebagai file.
  • Di Linux, /sysmenyediakan lebih banyak perangkat keras dan kontrol sistem.
  • Pada banyak varian unix, kontrol proses dapat dilakukan melalui sistem /procfile.
  • FUSE memudahkan untuk menulis sistem file baru. Sudah ada filesystem yang ada untuk mengonversi format file dengan cepat, mengakses file melalui berbagai protokol jaringan, mencari di dalam arsip, dll.

Mungkin masa depan shell unix bukanlah akses sistem yang lebih baik melalui perintah (dan struktur kontrol yang lebih baik untuk menggabungkan perintah) tetapi akses sistem yang lebih baik melalui sistem file (yang menggabungkan agak berbeda - saya tidak berpikir kami telah mengerjakan apa yang idiom kunci (seperti pipa shell) belum).


1
Anda memukul paku di kepala tepat setelah Anda mengatakan "Saya menduga ini yang Anda cari". Alasan utama saya mengajukan pertanyaan ini adalah bahwa saya suka memiliki kekuatan alat unix, tetapi interaksi berbasis teks antara program pasti 'menimbulkan penghalang untuk tugas yang lebih kompleks'. Saya telah menghabiskan cukup banyak hari pemrograman saya menulis parser teks :) Saya pikir ini adalah jawaban yang dipikirkan dengan sangat baik. Itu sampai ke inti masalah dan kompleksitas subjek. Saya berharap saya bisa membesarkannya dua kali: P
Robert S Ciaccio

1
+1 untuk ipython, meskipun saya tidak tahu apa yang OP ingin lakukan.
Falmarri

1
Ini adalah jawaban yang bagus: Sejujurnya saya berpikir bahwa benih-benih tesis PhD yang menarik ada di sini.
Ziggy

1
@RobertSCiaccio Jawaban ini baru saja ditautkan di pos baru-baru ini, dan komentar Anda tentang parsing teks membuat saya berpikir ... jika parsing teks sudah cukup untuk menyelesaikan "tugas kompleks" Anda, maka Anda tidak dapat memiliki skrip atau program kecil yang mengimplementasikan dan menggunakannya sebagai semacam fungsi di skrip bash Anda? Hanya berpikir, saya tidak punya banyak pengalaman bash scripting di bawah ikat pinggang saya untuk berbicara tentang.
Oxwivi

1
@onlyanegg Dengan cara apa ikan bisa dikatakan "berorientasi objek"? Ikan terutama bertujuan lebih sederhana. Apakah ada cara yang lebih kuat daripada alternatif?
Gilles 'SO- stop being evil'

13

Anda tidak perlu banyak kode bash untuk mengimplementasikan kelas atau objek di bash.

Katakanlah, 100 baris.

Bash memiliki array asosiatif yang dapat digunakan untuk mengimplementasikan sistem objek sederhana dengan pewarisan, metode, dan properti.

Jadi, Anda mungkin mendefinisikan kelas seperti ini:

class Queue N=10 add=q_add remove=q_remove

Membuat instance dari Antrian ini dapat dilakukan seperti ini:

class Q:Queue N=100

atau

inst Q:Queue N=100

Karena kelas diimplementasikan dengan sebuah array, kelas dan inst benar-benar sinonim - semacam seperti di javascript.

Menambahkan item ke antrian ini dapat dilakukan seperti ini:

$Q add 1 2 aaa bbb "a string"

Menghapus item ke dalam variabel X dapat dilakukan seperti ini:

$Q remove X

Dan struktur dumping suatu objek dapat dilakukan seperti ini:

$Q dump

Yang akan mengembalikan sesuatu seperti ini:

Q {
      parent=Queue {
                     parent=ROOT {
                                   this=ROOT
                                   0=dispatch ROOT
                                 }
                     class=Queue
                     N=10
                     add=q_add
                     remove=q_remove
                     0=dispatch Queue
                   }
      class=Q
      N=4
      add=q_add
      remove=q_remove
      0=dispatch Q
      1=
      2=ccc ddd
      3=
      4=
    }

Kelas dibuat menggunakan fungsi kelas seperti ini:

class(){
    local _name="$1:"                            # append a : to handle case of class with no parent
    printf "$FUNCNAME: %s\n" $_name
    local _this _parent _p _key _val _members
    _this=${_name%%:*}                           # get class name
    _parent=${_name#*:}                          # get parent class name
    _parent=${_parent/:/}                        # remove handy :
    declare -g -A $_this                         # make class storage
    [[ -n $_parent ]] && {                       # copy parent class members into this class
        eval _members=\"\${!$_parent[*]}\"       # get indices of members
        for _key in $_members; do                # inherit members from parent
            eval _val=\"\${$_parent[$_key]}\"    # get parent value
            eval $_this[$_key]=\"$_val\"         # set this member
        done
    }
    shift 1

    # overwrite with specific values for this object
    ROOT_set $_this "$@" "0=dispatch $_this" "parent=${_parent:-ROOT}" "class=$_this"
}

CATATAN: Saat mendefinisikan kelas atau instance baru, Anda dapat mengesampingkan nilai atau fungsi anggota apa pun.

Array asosiatif Bash memiliki kekhasan yang membuat pekerjaan ini rapi: $ Q [0]} identik dengan $ Q. Ini berarti bahwa kita dapat menggunakan nama array untuk memanggil fungsi pengiriman metode:

dispatch(){
    local _this=$1 _method=$2 _fn
    shift 2
    _fn="$_this[$_method]"                       # reference to method name
    ${!_fn} $_this "$@"
}

Sisi buruknya adalah saya tidak dapat menggunakan [0] untuk data sehingga antrian saya (dalam hal ini) mulai dari indeks = 1. Atau saya bisa menggunakan indeks asosiatif seperti "q + 0".

Untuk mendapatkan dan mengatur anggota Anda dapat melakukan sesuatu seperti ini:

# basic set and get for key-value members
ROOT_set(){                                       # $QOBJ set key=value
    local _this=$1 _exp _key _val
    shift
    for _exp in "$@"; do
        _key=${_exp%%=*}
        _val="${_exp#*=}"
        eval $_this[$_key]=\"$_val\"
    done
}

ROOT_get(){                                       # $QOBJ get var=key
    local _this=$1 _exp _var _key
    shift
    for _exp in "$@"; do
        _var=${_exp%%=*}
        _key=${_exp#*=}
        eval $_var=\"\${$_this[$_key]}\"
    done
}

Dan untuk membuang struktur objek, saya membuat ini:

CATATAN: Ini tidak diperlukan untuk OOP dalam bash, tetapi menyenangkan untuk melihat bagaimana objek dibuat.

# dump any object
obj_dump(){                                      # obj_dump <object/class name>
    local _this=$1 _j _val _key; local -i _tab=${2:-(${#_this}+2)}  # add 2 for " {"
    _tab+=2                                      # hanging indent from {
    printf "%s {\n" $_this
    eval "_key=\"\${!$_this[*]}\""
    for _j in $_key; do                          # print all members
        eval "_val=\"\${$_this[\$_j]}\""
        case $_j in
            # special treatment for parent
            parent) printf "%*s%s=" $_tab "" $_j; ${!_val} dump $(( _tab+${#_j}+${#_val}+2 ));;
                 *) printf "%*s%s=%s\n" $_tab "" $_j "$_val";;
        esac
    done
    (( _tab-=2 ))
    printf "%*s}\n" $_tab ""
    return 0
}

Desain OOP saya belum mempertimbangkan objek di dalam objek - kecuali kelas bawaan. Anda bisa membuatnya secara terpisah, atau membuat konstruktor khusus seperti kelas (). * obj_dump * perlu dimodifikasi untuk mendeteksi kelas internal untuk mencetaknya secara rekursif.

Oh! dan saya secara manual mendefinisikan kelas ROOT untuk menyederhanakan fungsi kelas :

declare -gA ROOT=(    \
  [this]=ROOT         \
  [0]="dispatch ROOT" \
  [dump]=obj_dump     \
  [set]="ROOT_set"    \
  [get]="ROOT_get"    \
)

Dengan beberapa fungsi antrian, saya mendefinisikan beberapa kelas seperti ini:

class Queue          \
    in=0 out=0 N=10  \
    dump=obj_dump    \
    add=q_add        \
    empty=q_empty    \
    full=q_full      \
    peek=q_peek      \
    remove=q_remove

class RoughQueue:Queue     \
    N=100                  \
    shove=q_shove          \
    head_drop=q_head_drop

Membuat beberapa contoh Antrian dan membuatnya berfungsi:

class Q:Queue N=1000
$Q add aaa bbb "ccc ddd"
$Q peek X
$Q remove X
printf "X=%s\n" "$X"
$Q remove X
printf "X=%s\n" "$X"
$Q remove X
printf "X=%s\n" "$X"


class R:RoughQueue N=3
$R shove aa bb cc dd ee ff gg hh ii jj
$R dump

Mungkin bekerja tapi jelek . Dan sama sekali bukan untuk apa bash. Mengingatkan saya pada jawaban Stephane tentang mengapa tidak menggunakan loop shell untuk memproses teks, khususnya bagian yang mengarah "secara konseptual" yang merinci perbedaan tujuan antara bahasa seperti C dan bash. unix.stackexchange.com/a/169765/135943
Wildcard

1
Mungkin bekerja? Itu memang berhasil, tetapi poin Anda adalah bahwa, meskipun tidak salah, itu tidak dilakukan. Saya juga tidak menjawab pertanyaan OP, tetapi jika bash adalah TC maka saya pikir itu harus dapat memproses objek. Dan banyak yang telah menunjukkan ini.
philcolbourn


5

IPython secara mengejutkan nyaman digunakan.

Fitur-fitur standar shell: kontrol pekerjaan, pengeditan dan riwayat readline, alias, cat ls cddan pwd, integrasi pager, menjalankan perintah sistem apa pun dengan mengawalinya dengan !atau mengaktifkan %rehashx, output perintah dapat diberikan ke variabel python, nilai-nilai python tersedia sebagai variabel shell.

Khusus python: menggunakan kembali hasil dari perintah terakhir, akses cepat ke dokumentasi dan sumber, pemuatan modul, debugger. Beberapa dukungan cluster jika Anda suka itu.

Yang mengatakan, menjalankan pipa kompleks tidak dilakukan dengan Python; Anda akan menggunakan shell posix juga, hanya dengan beberapa lem untuk meneruskan nilai ke sana kemari.



2

jq bekerja sangat baik seperti semacam lapisan berorientasi objek.


2

Yang ini sedikit lebih mudah digunakan dan diatur, bernama args, dll. Https://github.com/uudruid74/bashTheObjects

Saya memperbarui jawaban saya dengan contoh, yang mengikuti salah satu contoh dasar yang diberikan untuk jawaban lain, tetapi dengan sintaks ini. Contoh programnya mirip, tetapi Anda tidak harus mengawali semua variabel dengan nama kelas (ia tahu ini seperti yang ditunjukkan oleh metode kindof ) dan saya pikir sintaksnya jauh lebih sederhana!

Pertama, file kelas. Default untuk variabel instan adalah opsional dan hanya digunakan jika Anda tidak meneruskan nilai-nilai ini ke konstruktor.

class Person
    public show
    public set
    public Name
    public Age
    public Sex
    inst var Name "Saranyan"
    inst var Age 10
    inst var Sex "Male"

Person::Person { :; }
Person::set() { :; }
Person::Name() { println $Name }
Person::Age() { println $Age }
Person::Sex() { println $Sex }
Person::show() {
    Person::Name
    Person::Age
    Person::Sex
}

Sekarang sebagai contoh penggunaan:

#!/bin/bash
source static/oop.lib.sh

import Person

new Person Christy Name:"Christy" Age:21 Sex:"female"
new Person Evan Name:"Evan" Age:41 Sex:"male"

println "$(Evan.Name) is a $(Evan.Sex) aged $(Evan.Age)"
println "$(Christy.Name) is a $(Christy.Sex) aged $(Christy.Age)"
println "Stats for Evan ..."
Evan.show

assert 'kindof Person Evan'
assert '[ $Evan = $Evan ]'
assert 'kindof Person Christy'
assert '[ $Evan = $Christy ]'

CATATAN:

  1. Pernyataan terakhir itu akan gagal. Berbeda dengan contoh di atas, perpustakaan belum mendukung penugasan objek, tapi itu tidak akan terlalu sulit untuk ditambahkan. Saya akan meletakkannya di TO-DO saya bersama dengan dukungan container / iterator yang akan datang.

Pernyataan impor secara teknis tidak diperlukan, tetapi memaksa pemuatan kelas pada titik yang diberikan alih-alih menunggu yang baru , yang dapat membantu menginisialisasi hal-hal dalam urutan yang tepat. Catat kemudahan di mana Anda dapat mengatur beberapa variabel instan sekaligus.

Ada juga level debug, konstruktor, destruktor, subclassing , dan sistem refleksi dasar , dan yang ditampilkan adalah print / println untuk mengganti echo (pernah mencoba mencetak variabel yang dimulai dengan tanda hubung?). Contoh pada github menunjukkan itu berjalan sebagai CGI menghasilkan HTML dari kelas.

Perpustakaan itu sendiri (oop.lib.sh) tidak sesederhana itu (400+ baris, 11K), tetapi Anda cukup memasukkannya dan melupakannya.



1

Jika seseorang hanya menginginkan dasar-dasar pemrograman berorientasi objek (properti dan metode) daripada kerangka kerja yang sangat sederhana akan melakukan trik.

Katakanlah Anda ingin menampilkan teks "Hello World" menggunakan objek. Pertama, Anda membuat kelas objek yang memiliki properti untuk teks yang akan ditampilkan dan memiliki beberapa metode untuk mengatur teks ini dan menampilkannya. Untuk menunjukkan bagaimana beberapa instance kelas dapat bekerja bersama, saya telah menambahkan dua metode untuk menampilkan teks: satu dengan NewLine di akhir dan satu tanpa itu.

File definisi kelas: EchoClass.class

# Define properties
<<InstanceName>>_EchoString="Default text for <<InstanceName>>"

# Define methods
function <<InstanceName>>_SetEchoString()
{
  <<InstanceName>>_EchoString=$1
}

function <<InstanceName>>_Echo()
{
  # The -ne parameter tells echo not to add a NewLine at the end (No Enter)
  echo -ne "$<<InstanceName>>_EchoString"
}

function <<InstanceName>>_EchoNL()
{
  echo "$<<InstanceName>>_EchoString"
}

Harap perhatikan kata "<<InstanceName>>". Ini akan diganti nanti untuk membuat beberapa instance objek kelas. Sebelum Anda dapat menggunakan instance objek, Anda memerlukan fungsi yang sebenarnya membuatnya. Untuk menjaga hal-hal sederhana itu akan menjadi skrip terpisah yang disebut: ObjectFramework.lib

# 1st parameter : object instance name
# 2nd parameter : object instance class

function CreateObject()
{
  local InstanceName=$1
  local ObjectClass=$2
  # We will replace all occurences of the text "<<InstanceName>>" in the class file 
  # to the value of the InstanceName variable and store it in a temporary file
  local SedString='s/<<InstanceName>>/'$InstanceName'/g '$ObjectClass'.class'
  local TmpFile=$ObjectClass'_'$InstanceName'.tmp'
  sed $SedString > $TmpFile

  # The file will contain code which defines variables (properties) and functions (methods)
  # with the name we gave to our object instance via the 1st parameter of this function
  # ... we run this code so the variables and functions are actually defined in runtime
  source "$TmpFile"

  # Than remove the temp file as we don't need it any more
  rm "$TmpFile"
}

Jadi sekarang kita memiliki file definisi kelas dan fungsi CreateObject yang membuat salinan file ini dengan teks "<<InstanceName>>" diganti dengan nama apa pun yang kita inginkan.

Mari kita gunakan objek baru kita dalam skrip bernama: HelloWorld.sh (harap dicatat bahwa HelloWorld.sh harus dapat dieksekusi. Dua file lainnya tidak perlu)

# Define the CreateObject function via the lib file we created
source ObjectFramework.lib

# Create two instances of the EchoClass class
CreateObject MyHello EchoClass
CreateObject MyWorld EchoClass

# Call the SetEchoString method of the two objects. In reality these are 
# just two identical functions named differently and setting different
# variables (remember the <<InstanceName>>_EchoString variable?)
MyHello_SetEchoString "Hello "
MyWorld_SetEchoString "World"

# Finally we call the Echo and EchoNL (NewLine) methods
MyHello_Echo
MyWorld_EchoNL

Dengan menjalankan skrip HelloWorld.sh, ia menampilkan teks "Hello World" (dan menambahkan NewLine). Tidak ada yang akan terkesan banyak dengan hasil ini, namun kita akan tahu ini tidak sesederhana kelihatannya :)

Selamat coding!


Lebih baik membuat hal-hal kompleks menjadi sederhana daripada membuat hal-hal sederhana menjadi kompleks.
Wildcard

1

Ini adalah shell berorientasi objek yang berbasis di Python, tetapi memiliki sintakse tutup Golang: https://github.com/alexst07/shell-plus-plus

Misalnya, coba tangkap:

try {
  git clone git@github.com:alexst07/shell-plus-plus.git
} catch InvalidCmdException as ex {
  print("git not installed [msg: ", ex, "]")
}

kelas dan kelebihan operator:

class Complex {
  func __init__(r, i) {
    this.r = r
    this.i = i
  }

  func __add__(n) {
    return Complex(n.r + this.r, n.i + this.i)
  }

  func __sub__(n) {
    return Complex(n.r - this.r, n.i - this.i)
  }

  func __print__() {
    return string(this.r) + " + " + string(this.i) + "i"
  }
}

c1 = Complex(2, 3)
c2 = Complex(1, 2)
c = c1 + c2

print(c)

dan Anda dapat menggunakan perintah bash serupa:

echo "Test" | cat # simple pipeline
ls src* | grep -e "test" # using glob

# using variables content as command
cip = "ipconfig"
cgrep = ["grep", "-e", "10\..*"]
${cip} | $@{cgrep} # pass an array to command

0

Sekarang, dengan benda apa yang Anda hadapi sebagian besar waktu? Ini file / direktori, proses dan interaksinya. Jadi harus suka f1.editatau semacamnya currentFile=f1.c ; .edit ; .compile ; .run. Atau d1.search(filename='*.c' string='int \*'). Atau p1.stop, p1.bg. Itulah pemahaman saya tentang ooshell.


0
## implemantion of base class
function Class()
{
    base=${FUNCNAME}
    this=${1}
    Class_setCUUID $this
    for method in $(compgen -A function)
    do
        export ${method/#$base\_/$this\_}="${method} ${this}"
    done

}

function copyCUUID()
{
        export ${2}_CUUID=$(echo $(eval "echo \$${1}_CUUID"))

}

function Class_setCUUID()
{
        export ${1}_CUUID=$(uuid)
}

function Class_getCUUID()
{
        echo $(eval "echo \$${2}_CUUID")
}


function Class_setProperty()
{
        export ${1}_${2}=${3}
}

function Class_getProperty()
{
        echo $(eval "echo \$${1}_${2}")
}

function Class_Method()
{
        echo "function ${1}_${2}()
        {
        echo null
        }
        " > /tmp/t.func
        . /tmp/t.func
        rm /tmp/t.func


}

function Class_setMethod()
{
        export ${1}_${2}=${1}_${2}
}


function Class_getMethod()
{
        $(eval "echo \$${1}_${2}")
}


function Class_equals()
{
        base="Class"
        this=${2}

    copyCUUID ${1} ${2}
    for method in $(compgen -A function)
    do
        export ${method/#$base\_/$this\_}="${method} ${1}"
    done


}

baru saja mencoba memperkenalkan konsep oo ke bash berdasarkan referensi http://hipersayanx.blogspot.in/2012/12/object-oriented-programming-in-bash.html

source ./oobash

Class person
$person_setProperty Name "Saranyan"
$person_setProperty Age 10
$person_setProperty Sex "Male"
function person_show()
{
$person_getProperty Name
$person_getProperty Age
$person_getProperty Sex
}
$person_setMethod show

$person_equals person1
$person1_getMethod show
$person1_equals person3
$person_getCUUID person
$person_getCUUID person1
$person_getCUUID person3

0

Maaf untuk jawaban singkat tapi ini dia.

hipersayanx telah membuat artikel Pemrograman Berorientasi Objek di Bash . Pada dasarnya ia dibajak $FUNCNAME, function, compgen, dan exportuntuk membuat sebagai dekat dengan OOP satu bisa mendapatkan di bash.

Bagian yang keren adalah ini bekerja dengan baik dan seseorang hanya perlu beberapa baris boilerplating untuk membangun kelas.

Bagian dasar yang dibutuhkan adalah:

ClassName() {
# A pointer to this Class. (2)
base=$FUNCNAME
this=$1

# Inherited classes (optional).
export ${this}_inherits="Class1 Class2 Class3" # (3.1)
 for class in $(eval "echo \$${this}_inherits")
do
    for property in $(compgen -A variable ${class}_)
    do
        export ${property/#$class\_/$this\_}="${property}" # (3.2)
    done

    for method in $(compgen -A function ${class}_)
    do
        export ${method/#$class\_/$this\_}="${method} ${this}"
    done
done

# Declare Properties.
export ${this}_x=$2
export ${this}_y=$3
export ${this}_z=$4

# Declare methods.
for method in $(compgen -A function); do
    export ${method/#$base\_/$this\_}="${method} ${this}"
done
}

function ClassName_MethodName()
{
#base is where the magic happens, its what holds the class name
base=$(expr "$FUNCNAME" : '\([a-zA-Z][a-zA-Z0-9]*\)')
this=$1

x=$(eval "echo \$${this}_x")

echo "$this ($x)"
}

Pemakaian:

# Create a new Class Instance
ClassName 'instanceName' $param1 $param2

$instanceName_method

Sekarang, saya telah menggunakan ini sendiri dalam proyek AuditOps saya dan hipersayanx memiliki rincian lebih lanjut tentang bagaimana ini sebenarnya bekerja di situsnya. Peringatan tarif meskipun ini sangat bashism tidak akan bekerja dengan apa pun yang lebih tua dari bash 4.0 dan dapat menyebabkan sakit kepala dalam debugging. Sementara secara pribadi saya ingin melihat sebagian besar dari pelapisan ketel redone sebagai kelas itu sendiri.

Itu selalu lebih bijaksana untuk menggunakan bahasa scripting OOP yang serius seperti perl, ruby, dan python ketika lebih cocok untuk proyek Anda. Namun dalam pilihan jujur ​​saya nilainya waktu dan usaha ketika mempertahankan skrip bash modular untuk memanfaatkan metode OOP ini di bash.


0

Saya sedang mengembangkan di GitHub sebuah fungsi yang berfungsi seperti Objek HashMap , shell_map .

Untuk membuat " instance HashMap " fungsi ini dapat membuat salinan dirinya sendiri dengan nama yang berbeda. Setiap salinan fungsi baru akan memiliki variabel $ FUNCNAME yang berbeda. $ FUNCNAME kemudian digunakan untuk membuat namespace untuk setiap instance Map.

Kunci peta adalah variabel global, dalam bentuk $ FUNCNAME_DATA_ $ KEY, di mana $ KEY adalah kunci yang ditambahkan ke Peta. Variabel-variabel ini adalah variabel dinamis .

Di bawah ini saya akan meletakkan versi yang disederhanakan sehingga Anda dapat menggunakan sebagai contoh.

#!/bin/bash

shell_map () {
    local METHOD="$1"

    case $METHOD in
    new)
        local NEW_MAP="$2"

        # loads shell_map function declaration
        test -n "$(declare -f shell_map)" || return

        # declares in the Global Scope a copy of shell_map, under a new name.
        eval "${_/shell_map/$2}"
    ;;
    put)
        local KEY="$2"  
        local VALUE="$3"

        # declares a variable in the global scope
        eval ${FUNCNAME}_DATA_${KEY}='$VALUE'
    ;;
    get)
        local KEY="$2"
        local VALUE="${FUNCNAME}_DATA_${KEY}"
        echo "${!VALUE}"
    ;;
    keys)
        declare | grep -Po "(?<=${FUNCNAME}_DATA_)\w+((?=\=))"
    ;;
    name)
        echo $FUNCNAME
    ;;
    contains_key)
        local KEY="$2"
        compgen -v ${FUNCNAME}_DATA_${KEY} > /dev/null && return 0 || return 1
    ;;
    clear_all)
        while read var; do  
            unset $var
        done < <(compgen -v ${FUNCNAME}_DATA_)
    ;;
    remove)
        local KEY="$2"
        unset ${FUNCNAME}_DATA_${KEY}
    ;;
    size)
        compgen -v ${FUNCNAME}_DATA_${KEY} | wc -l
    ;;
    *)
        echo "unsupported operation '$1'."
        return 1
    ;;
    esac
}

Pemakaian:

shell_map new credit
credit put Mary 100
credit put John 200
for customer in `credit keys`; do 
    value=`credit get $customer`       
    echo "customer $customer has $value"
done
credit contains "Mary" && echo "Mary has credit!"

Anda tampaknya salah paham bagaimana cara kerja substitusi perintah. Itu diganti dengan output dari perintah yang terkandung dalam backticks, tidak diganti dengan status pengembalian . Dengan kata lain kode Anda tidak melakukan apa yang Anda pikirkan.
Wildcard

Aha. Anda benar. Permintaan maaf saya. Namun, itu akan jauh lebih jelas untuk digunakan carp "Some error message"; return.
Wildcard

Atau [ -z "$KEY" ] && { carp "some message"; return;} Tidak perlu subkulit. Tetapi sebenarnya itu tampak seperti kandidat yang sebenarnya untuk sebuah if ... elif ... elif ... else ... fikonstruksi — yang seringkali bukan pilihan terbaik, tetapi mungkin di sini. :) (Atau mungkin saklar kasus.)
Wildcard

@ Kartu Memori Saya mengedit jawabannya. Sekarang diskusi kita tentang ikan mas dan backticks tidak masuk akal. mari kita hapus percakapan ini?
Bruno Negrão Zica

0

Timah hitam adalah bahasa shell mirip-Python. Ini memaketkan shell seperti sintaksis dengan Python yang membuat pengalaman berorientasi objek.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.