むンフェルノシェル

FAQ OS Infernoずは䜕ですか、なぜ必芁なのですか

長幎のInferno OSシェルは、非垞に吊定的な感情を匕き起こしたした。 そしお、私はむンフェルノshで䜕人かの人々が喜んでいるこずに気づいたこずがなかった。 しかし、圌らが蚀うように、それは決しお遅いよりはたしです-今日、私はシェルに慎重に察凊するこずに決めたした、そしお結果ずしお、私も感銘を受けたした-これは本圓にナニヌクなこずです 信じられないほど゚レガントでシンプル。

それでも、客芳性を高めるために欠点から始めたす。 䞻なこずは、シェルが非垞に遅いこずです。 理由は/dis/sh.disたせんが、すべおのシェルがむンフェルノ実際にはいく぀かありたすが、珟圚は/dis/sh.disに぀いお話しお/dis/sh.dis は非垞に遅いです。 これは非垞に奇劙です 通垞、LimboJITモヌドで蚘述されたアプリケヌションの速床は、CずPerlなどの高速スクリプト蚀語の速床の間です。 したがっお、 sh本栌的なアプリケヌションは機胜したせん。 しかし、それにもかかわらず、くしゃみごずにLimboを発芋するのは䞍䟿です。そのため、すべおの同じ開始スクリプトやその他の小さなこずをshで蚘述する必芁がありたす。 2番目の重倧な欠点は、テキストコン゜ヌルで䜿甚するこずの䞍䟿さ、コマンド履歎の欠劂、自動補完、入力時の䟿利な線集が非垞にうっずうしいこずですしかし、私はrlwrapナヌティリティに぀いお聞いたずころです。 第䞉-このシェルの構文は、察になっおいない匕甚笊を䜿甚するこずは珍しく、絶察に他のシェルのバックラむトを䜿甚しおスクリプトの構文を匷調しようずするずむンファナルの既補のバックラむトがないため完党な悪倢に぀ながりたす。 今日、この問題を解決するために、vimの構文匷調衚瀺を実装したした。そのため、シェルに察凊するために座りたした。その結果、構文匷調衚瀺の代わりに、抵抗できず、この蚘事を曞いおいたす。 :)

内容




私たちのスクリプトは䜕から、䜕から、䜕から䜜られおいたすか


/dis/sh.disサポヌトされる機胜は印象的です 条件付きステヌトメントずルヌプさえありたせん 機胜なし。 そしお、䜕がそこにあり、これらの条件にどのように存圚するこずができたすか ご芧ください。 だから䜕ですか
おそらく、最埌のポむントを芋お、「あは いく぀かの特別なチヌム。 確かに圌らは残りをしたす、すべおが汚いです。」 しかし、いいえ、あなたは掚枬したせんでした。 組み蟌みコマンドのうち、通垞はexit 、 run 、およびload 3぀が䜿甚されload 。 䞀般的に䜿甚される文字列コマンドはquoteずunquoteです。 runに぀いおは、珟圚のシェルアナログ.たたはbashのsourceで指定されたスクリプトを実行するだけです。

しかし、 load -はい、それは爆匟です Limboで䜜成された远加モゞュヌルを珟圚のシェルにロヌドし、関数、䟋倖、正芏衚珟、数孊挔算などの堎合、シェルに機胜を完党に远加できたす。 など これらのモゞュヌルを動的にアンロヌドできるunloadコマンドもありたす。 :)それにも関わらず、ロヌド可胜なモゞュヌルがなくおも、シェルは完党に機胜的です-これを「裞のsh」にifずforを実装するこずで、蚘事の最埌で蚌明したす

ああ、私が蚀及するのを忘れおいた䜕か。 今は確かに「ああ」だず思いたすか圌はただコメントを支持しおいたす。 #始たる。 :)

アプリケヌションを起動する


* nixシェルずほずんど同じです

 ; echo one two | wc 1 2 8 

しかし、違いがありたす。

远加のコマンドI / Oリダむレクト

最埌の機胜は特に興味深いものです。 たずえば、2぀のcmpファむルをヘルプず比范する暙準コマンドは、ファむルではなく、他の2぀のコマンドの結果を比范できたす cmp <{ ls /dir1 } <{ ls /dir2 } 。

$ステヌタス

終了ステヌタスアプリケヌションコヌドを実装するための非垞に珍しいアプロヌチ。 埓来のオペレヌティングシステムでは、すべおのプログラムは数字で終了したす。すべおが正垞な堎合は0、倱敗した堎合はその他のプログラムです。 infernoでは、すべおのプログラムは単玔に終了するかすべおが正垞に凊理されおいる堎合、䟋倖をスロヌしたす。䟋倖の倀ぱラヌテキストを含む文字列です。

これが通垞の゚ラヌである堎合、この行は「fail」で始たる必芁がありたす。 アプリケヌションは「クラッシュ」したせんでしたが、この゚ラヌをこのアプリケヌションを起動したナヌザヌに返すこずで終了したいだけです通垞、これはシェルです。 ゚ラヌが「fail」で始たらない堎合、アプリケヌションが終了した埌、そのプロセスはメモリに残り「壊れた」状態、デバッガヌで調べお、この䟋倖が発生した理由を芋぀けるこずができたす保存する代わりに、コアダンプに類䌌メモリ内のディスクでハングしたす。

したがっお、実行䞭のコマンドの完了埌、その「終了コヌド」-぀たり 䟋倖゚ラヌテキストは$status環境倉数にありたす「fail」以倖の䟋倖テキストに䜕も含たれおいない堎合、「 $status 」行は「failed」になり$status 。

行、行リスト、コマンドブロック


Infernovシェルは、文字列ず文字列のリストのみを扱いたす。

ひも

文字列は、スペヌスや特殊文字を含たない単語、たたは䞀重匕甚笊で囲たれた文字です。 そのような文字列内の唯䞀の「゚スケヌプ可胜な」文字は、単䞀匕甚笊自䜓であり、2぀のそのような匕甚笊で蚘述されおいたす。
 ; echo 'quote '' <-- here' quote ' <-- here 

\ n、\ t、倉数の補間などはありたせん in rowsはサポヌトされおいたせん。 文字列に改行文字を挿入する必芁がある堎合は、そのたたEnterキヌを抌しお貌り付けるか、この文字を含む倉数ず文字列を連結したす。 infernoには、コヌドによっお任意の文字を出力できるunicode1ナヌティリティがありたす。これは、ヘルプを䜿甚しお行われたす構造"{}に぀いおは以䞋で説明したすが、珟時点ではbash ``類䌌物ず考えおください
 ; cr="{unicode -t 0D} ; lf="{unicode -t 0A} ; tab="{unicode -t 09} ; echo -n 'a'$cr$lf'b'$tab'c' | xd -1x 0000000 61 0d 0a 62 09 63 0000006 

文字列には二重匕甚笊は䜿甚されたせんちなみに、二重二重匕甚笊はむンファヌンシェルでは䜕にも䜿甚されたせん。

コマンドブロック

コマンドのブロックは䞭括匧内に曞き蟌たれ、ブロック党䜓がシェルによっお1行ずしお凊理されたす䞭括匧内の文字を含む。
 ; { echo one; echo two } one two ; '{ echo one; echo two }' one two 

単䞀匕甚笊でshれた文字列ずの唯䞀の違いは、 shがコマンドブロックの構文をチェックし、それらをよりコンパクトな行に再フォヌマットするこずです。
 ; echo { cmd | } sh: stdin: parse error: syntax error ; echo { cmd | cmd } {cmd|cmd} ; echo { echo one echo two } {echo one;echo two} 


行のリスト

文字列のリストは、空癜文字で区切られたれロ個以䞊の文字列です。 これらは括匧で囲むこずができたすが、ほずんどの堎合、これは必芁ありたせん。

シェルコマンドは、 単に行のリストです。最初の行にはコマンドたたはコヌドブロックが含たれ、残りの行はそれらのパラメヌタヌです。
 ; echo one two three one two three ; echo (one two) (three) one two three ; (echo () (one (two three))) one two three ; ({echo Hello, $1!} World) Hello, World! 

文字列のリストを連結するには、 ^挔算子を䜿甚したす。 同じ数の芁玠を含む2぀のリストに適甚できたす芁玠はペアで連結されたす、たたはリストの1぀に芁玠が1぀だけ含たれおいる必芁があり、2番目のリストの各芁玠ず連結されたす。 特別な堎合ずしお、䞡方のリストにそれぞれ1぀の芁玠しか含たれおいない堎合、2行の通垞の連結が取埗されたす。
 ; echo (abc) ^ (1 2 3) a1 b2 c3 ; echo (ab) ^ 1 a1 b1 ; echo 1 ^ (ab) 1a 1b ; echo a ^ b ab 

通垞、1぀のシェルコマンドを1行で蚘述する必芁がありたす。「次の行でコマンドを続行する」こずを瀺す特別な文字はありたせん。 しかし、コマンドを耇数の行に分割するこずは非垞に簡単です。前の行の行単䞀匕甚笊たたはコマンドブロック䞭括匧たたは行のリスト括匧を開いたり閉じたりせず、リスト連結挔算子で前の行を終了したす。

環境倉数


地獄のシェルで倉数を操䜜するこずは、埓来のシェルに䞀芋䌌おいたすが、だたされおはいけたせん
 ; a = 'World' ; echo Hello, $a! Hello, World! 


/ env

Inferno OSの環境倉数は、埓来のOSずは異なる方法で実装されたす。 環境倉数を操䜜し、 int execvpe(const char *file, char *const argv[], char *const envp[]);ような悪倢を通しお各プロセスに枡すための远加のPOSIX APIを導入する代わりに 環境倉数は、単に/envディレクトリ内のファむルです。 これは興味深い可胜性を提䟛したす。たずえば、アプリケヌションは/envを゚クスポヌト listen1およびexport4経由するだけで、ネットワヌク経由で他のアプリケヌションに環境倉数ぞのアクセスを提䟛できたす。

/envファむルを䜜成、削陀、倉曎するこずにより、環境倉数を䜜成/削陀/倉曎できたす。 ただし、珟圚のshはメモリ内のすべおの環境倉数のコピヌを保持しおいるため、 /env内のファむルを介しお行われた倉曎では、珟圚のshではなくアプリケヌションが起動されたす。 䞀方、シェルの通垞の方法で =挔算子を䜿甚しお倉数を倉曎するず、 /envファむルが自動的に曎新されたす。

シェル倉数名には、次の文字を含めるこずができたす。 ファむル名に䜿甚できないものたずえば、names . 、 .. 、および/を含む。 このような名前の倉数は、珟圚のshでのみ䜿甚でき、起動したアプリケヌションには衚瀺されたせん。

リスト

別の重芁な違いは、すべおの倉数に文字列のリストのみが含たれおいるこずです。 1行を倉数に入れるこずはできたせん-それは垞に1行のリストになりたす。

空のリストを倉数に保存するず明瀺的にa=()を割り圓おるか、暗黙的にa=を介しa= 、倉数が削陀されたす。

 ; var = 'first str' second ; echo $var first str second ; echo $#var 2 ; echo $"var first str second 

ご芧のずおり、 $varず$"var出力は芖芚的に異なりたせん。 echoはすべおのパラメヌタヌをスペヌスで衚瀺し、 $"は倉数のすべおの芁玠をスペヌスで結合するためです。 ただし、最初のechoコマンドは2぀のパラメヌタヌを受け取り、最埌のパラメヌタヌは受け取りたした。

倉数の倀を䜕らかの方法で暗黙的に連結するたびに、シェルは連結挔算子^挿入したす芚えおいるように、これは文字列ではなく文字列のリストで機胜したす。 これは䟿利ですが、習慣ではありたせんが、予期しないこずがありたす。
 ; flags = abc ; files = file1 file2 ; echo -$flags $files.b -a -b -c file1.b file2.b ; echo { echo -$flags $files.b } {echo -^$flags $files^.b} 

倉数のリストぞの割り圓おも機胜したす。 右偎のリストが巊偎の倉数よりも倚くの芁玠で構成されおいる堎合、最埌の倉数はリストの残りを受け取り、前の倉数ではそれぞれに1぀の芁玠がありたす。
 ; list = abcd ; (head tail) = $list ; echo $head a ; echo $tail bcd ; (xy) = (3 5) ; (xy) = ($y $x) ; echo 'x='^$x 'y='^$y x=5 y=3 

スクリプトたたはコヌドブロックのすべおのパラメヌタヌのリストは倉数$* 、個々のパラメヌタヌは倉数$1 、 $2 、...にありたす。

スコヌプ

コヌドの各ブロックは、独自のスコヌプを圢成したす。 挔算子=および:=しお、倉数に倀を割り圓おるこずができたす。 1぀目は、既存の倉数の倀を倉曎するか、珟圚のスコヌプに新しい倉数を䜜成したす。 2番目は垞に新しい倉数を䜜成し、珟圚のブロックの終わりたで、この名前存圚する堎合で倉数の叀い倀を䞊曞きしたす。
 ; a = 1 ; { a = 2 ; echo $a } 2 ; echo $a 2 ; { a := 3; echo $a } 3 ; echo $a 2 ; { b := 4; echo $b } 4 ; echo b is $b b is 


倉数参照

倉数名は、 $文字の埌の行です。 たた、任意の文字列単䞀匕甚笊たたは別の倉数を䜿甚できたす。
 ; 'var' = 10 ; echo $var 10 ; ref = 'var' ; echo $$ref 10 ; echo $'var' 10 ; echo $('va' ^ r) 10 


コマンド出力のむンタヌセプト


実際、このトピックはコマンドの起動を説明するセクションをより倚く参照しおいたすが、話しおいるこずを明確にするために、最初に文字列のリストを操䜜する方法を説明する必芁があったため、今たで延期しなければなりたせんでした。

構文の匷調衚瀺を氞遠に壊しおしたう非垞に䞍察の匕甚笊に䌚いたす。
䟋ずしお、 ls呌び出しを介しおファむルのリストをロヌドしたす。 ファむル名にスペヌスが含たれおいる可胜性があるため、 `{}暙準動䜜は機胜したせん。リスト項目を改行で区切るだけです。
 ; ifs := "{unicode -t 0A} ; files := `{ ls / } ; echo $#files 82 ; ls / | wc -l 82 

しかし実際には、シェルによっおファむル名のリストに展開されるファむル名テンプレヌトにより、より簡単で信頌性の高いものになりたす。
 ; files2 := /* ; echo $#files2 82 


組み蟌みコマンド


組み蟌みコマンドには、通垞のコマンドず文字列の操䜜甚の2぀のタむプがありたす。

通垞のコマンドは、アプリケヌション/スクリプトの起動ず同じ方法で呌び出されたす。
 ; run /lib/sh/profile ; load std ; unload std ; exit 

文字列を操䜜するためのコマンドは、 ${ }を介しお呌び出され、暙準の文字列を返したす぀たり、stdoutに出力せず、たずえば、倉数の倀ぞのアピヌルが返されたす。 これらは、通垞のコマンドのパラメヌタヌで䜿甚するか、倉数に倀を割り圓おる右偎で䜿甚する必芁がありたす。 たずえば、コマンド${quote}は、枡された文字列のリストを1行で${unquote} 、 ${unquote}は反察の操䜜を実行しお、1行を文字列のリストに倉換したす。
 ; list = 'ab' cd ; echo $list abcd ; echo ${quote $list} 'ab' cd ; echo ${unquote ${quote $list}} abcd 


if、for、関数を远加


私が玄束したように、これらの非垞に必芁なものを「裞のsh」で実装する方法を瀺したす。 もちろん、実際にはこれは必芁ありたせん。stdロヌド可胜モゞュヌルは必芁なものすべおを提䟛し、それを䜿甚する方がはるかに䟿利です。 しかし、それにもかかわらず、この実装は、裞のshの機胜のデモンストレヌションずしお興味深いものです。

すべおが排他的に䜿甚しお実装されたす


私たちは「機胜」を実行したす

前述したように、シェルコマンドは単なる行のリストです。最初の行はコマンドで、残りの行はそのパラメヌタヌです。 たた、シェルコマンドブロックは単なる文字列であり、倉数に保存できたす。 たた、コマンドブロックはすべお、パラメヌタヌを$* 、 $1などで受け取りたす。
 ; hello = { echo Hello, $1! } ; $hello World Hello, World! 

さらに、関数型プログラミングの最高の粟神で関数をカリヌ化するこずもできたす。 :)
 ; greet = {echo $1, $2!} ; hi = $greet Hi ; hello = $greet Hello ; $hi World Hi, World! ; $hello World Hello, World! 

別の䟋-ブロックパラメヌタヌを䜿甚しお、番号で目的のリストアむテムを取埗できたす。
 ; list = abcdef ; { echo $3 } $list c 


あなたのために

実装するこずに興味があり、最小限の機胜を実珟した堎合は、本栌的な䟿利なものを䜜成しようずしたせんでした。 forが必芁でしたルヌプを1回停止する必芁がありたすが、これを行うのに問題がある堎合は䞍芁です。
 ; do = { $* } ; dont = { } ; if = { (cmd cond) := $* { $2 $cmd } $cond $do $dont } ; for = { (var in list) := $* code := $$#* $iter $var $code $list } ; iter = { (var code list) := $* (cur list) := $list (next unused) := $list $if {$var=$cur; $code; $iter $var $code $list} $next } ; $for i in 10 20 30 { echo i is $i } i is 10 i is 20 i is 30 ; 


面癜いささいなこず


デフォルトでは、シェルはスクリプトの起動時に名前空間をフォヌクするため、スクリプトはそれを起動したプロセスの名前空間を倉曎できたせん。 これは、芪の名前空間を構成するだけのタスクを持぀スクリプトには適合したせん。 このようなスクリプトは#!/dis/sh -n始たる必芁がありたす。

loadedさloaded組み蟌みコマンドは、ロヌドされたすべおのモゞュヌルのすべおの組み蟌みコマンドをリストしたす。 たた、 whatis組み蟌みコマンドは、倉数、関数、コマンドなどに関する情報を衚瀺したす。

シェルモゞュヌルのリストを䜿甚しお倉数$autoloadを䜜成するず、これらのモゞュヌルは起動された各シェルに自動的にロヌドされたす。

シェルには構文糖のサポヌトがありたす &&および|| 。 これらの挔算子はbare shで䜿甚できたすが、組み蟌みのandおよびorコマンドの呌び出しに倉換されたす。これらはbare shではなく、 stdモゞュヌルからのものですしたがっお、 &&および||はload std埌にのみ䜿甚できたす。
 ; echo { cmd && cmd } {and {cmd} {cmd}} ; echo { cmd || cmd } {or {cmd} {cmd}} 

Limboで䜜成されたアプリケヌションは、たずえば、コマンドラむンパラメヌタヌで開始するずき、shコマンドのブロックを含む行は、 sh2モゞュヌルを䜿甚しお非垞に簡単に実行できたす。

倉数ず行リストを䜿甚したシェルの䜜業スタむルは、埓来のシェルずは異なり、最初に蚀及されたずきに、倉数のパラメヌタヌず倀を䞀床だけシヌルドするこずを考える必芁があるずいう事実に぀ながりたす。 そしお、それらが持っおいるシンボルを考えるこずなく、奜きな堎所にそれらを転送できたす。

たずめ


この短い蚘事は、むンフェルニアンシェルのほが完党なリファレンスガむドです。 ぀たり、基本的なシェルのすべおの機胜が詳现に、そしおすべおのニュアンスず䟋ずずもに説明されおいたす。 sh(1) , , $apid , $prompt , - , sh ., .

/, :
! «» , , if for ( , raise std — .. /bin/false :) run ).

, . , sh-std(1) :
しかし、これらの远加コマンドはすべお、シェル自䜓の構文を耇雑にするものではなく、単玔で゚レガントなたたです

Source: https://habr.com/ru/post/J161859/


All Articles