Mac OS X デスクトップで tcsh と sh を並べて表示する | |
| 原作者 | ビル・ジョイ |
|---|---|
| 初回リリース | 1978年 |
| 安定リリース | 6.20.00 / 2016年11月24日[1] |
| リポジトリ |
|
| 書かれた | C |
| オペレーティング·システム | BSD、UNIX、UNOS、Linux、macOS |
| タイプ | Unixシェル |
| ライセンス | BSDライセンス |

Cシェル( cshまたは改良版のtcsh ) は、1970 年代後半にカリフォルニア大学バークレー校の大学院生だったビル・ジョイによって作成されたUnix シェルです。ジョイが 1978 年に初めて配布したバークレー ソフトウェア ディストリビューション(BSD)の 2BSD リリースから始まり、広く配布されています。 [2] [3]アイデアやコードへの初期の貢献者には、マイケル・ユーベル、エリック・オールマン、マイク・オブライエン、ジム・カルプなどがいます。[4]
C シェルは、通常テキスト ウィンドウで実行されるコマンド プロセッサであり、ユーザーはこれを使用してコマンドを入力して実行できます。C シェルは、スクリプトと呼ばれるファイルからコマンドを読み取ることもできます。すべての Unix シェルと同様に、ファイル名のワイルドカード、パイプ、ヒア ドキュメント、コマンド置換、変数、条件テストと反復のための制御構造をサポートしています。特に 1980 年代において、C シェルが他のシェルと差別化されていたのは、その対話型機能と全体的なスタイルでした。新しい機能により、より簡単かつ迅速に使用できるようになりました。言語の全体的なスタイルはCに似ており、より読みやすいと見なされていました。
macOSやRed Hat Linuxなどの多くのシステムでは、 csh は実際にはcsh の改良版であるtcshです。多くの場合、2 つのファイルのうちの 1 つは、もう 1 つのファイルへのハード リンクまたはシンボリック リンクであるため、どちらの名前でも同じ C シェルの改良版を参照します。元の csh ソース コードとバイナリはNetBSDの一部です。
Debianとその派生版(Ubuntuを含む)には、cshとtcshという2つの異なるパッケージがあります。前者はcshのオリジナルのBSDバージョン[5] [6]に基づいており、後者は改良されたtcshです。[7] [8]
tcsh はファイル名とコマンドの補完、およびコマンド ライン編集の概念を追加しました。これはTenexシステムから借用したものです。これは "t" の由来です。[9] tcsh は機能の追加のみで既存のものを変更しなかったため、元の C シェルとの下位互換性が維持されました[10]。tcsh は Joy が作成した元のソース ツリーからのサイド ブランチとして始まりましたが、現在では開発が進行中のメイン ブランチになっています。tcsh は非常に安定していますが、新しいリリースはほぼ 1 年に 1 回リリースされ、ほとんどがマイナーなバグ修正で構成されています。[11]
設計目標と特徴
C シェルの主な設計目標は、 C プログラミング言語に似た外観にすることと、対話的な使用に適したものにすることでした。
Cに近い
Unix システムはほぼ完全に C で書かれていたため、C シェルの最初の目標は、システムの他の部分とスタイル的に一貫性のあるコマンド言語を作成することでした。キーワード、括弧の使用、C シェルの組み込み式文法、配列のサポートはすべて、C の影響を強く受けています。
今日の基準では、C シェルは、他の多くの一般的なスクリプト言語に比べて特に C に似ているようには思えないかもしれません。しかし、80 年代から 90 年代にかけて、特にベル研究所のStephen Bourneによって書かれた当時主流だったシェルであるBourne シェル( shとしても知られています) と比較すると、その違いは顕著でした。この例は、C シェルのより一般的な式演算子と構文を示しています。
ボーンシェル
#!/bin/sh
if [ $days -gt 365 ] then echoこれは1年以上です。fi
Cシェル
#!/bin/csh
if ( $days > 365 ) then
echoこれは1年以上です。
endif
Bourne sh には式文法がなかった。角括弧で囲まれた条件は、外部のテストプログラムを実行するという遅い手段で評価する必要があった。sh のコマンドは、その引数ワードを新しいコマンドとして受け取り、子プロセスifとして実行する。子プロセスがゼロの戻りコードで終了した場合、sh は節 (別の文だが、同じ行にセミコロンで結合して記述されることが多い) を探し、そのネストされたブロックを実行する。それ以外の場合は、else を実行する。テスト プログラムを " " と " " の両方としてハードリンクすると、角括弧の表記上の利点が得られ、test の機能が sh 言語の一部であるかのような印象を与える。sh が制御ブロックの終了を示すために逆のキーワードを使用するのは、 ALGOL 68から借用したスタイルである。[12]thentest[
対照的に、csh は式を直接評価できるため、処理が高速でした。また、可読性も優れているとされていました。その式では、主に C からコピーされた文法と演算子のセットが使用され、キーワードはどれも逆順にならず、全体的なスタイルも C に似ていました。
以下は、2 の最初の 10 乗を計算するスクリプトを比較する 2 番目の例です。
ボーンシェル
#!/bin/sh
i = 2
j = 1
while [ $j -le 10 ] do echo '2 **' $j = $i i = ` expr $i '*' 2 ` j = ` expr $j + 1 `完了
Cシェル
#!/bin/csh
set i = 2
set j = 1
while ( $j < = 10 )
echo '2 **' $j = $i
@ i * = 2
@j++ さん
終わり
式の文法がないため、sh スクリプトはコマンド置換とexprコマンドを使用します。(最新のPOSIX シェルにはそのような文法があり ます。ステートメントはi=$((i * 2))または と記述できます: "$((i *= 2))"。)
最後に、 switch ステートメントの異なるスタイルを示す 3 番目の例を示します。
ボーンシェル
#!/bin/sh
for i in d*
do case $i in d? ) echo $i is short ;; * ) echo $i is long ;; esac done
Cシェル
#!/bin/csh
foreach i ( d* )
switch ( $i )
case d?:
echo $i is short
breaksw
default :
echo $i is long
endsw
end
sh スクリプトでは、;;sh はそれ以外の場合は null ステートメントを許可しないため、" " は各ケースの終わりを示します。
インタラクティブな使用のための改善
2 つ目の目的は、C シェルを対話型でより使いやすくすることでした。ターミナルでコマンドを入力することで、より簡単、高速、そしてフレンドリーに使用できる多数の新機能が導入されました。ユーザーはキー入力を大幅に減らして作業を完了でき、実行速度も向上しました。これらの新機能の中で最も重要なのは、履歴と編集のメカニズム、エイリアス、ディレクトリ スタック、チルダ表記、cdpath、ジョブ制御、パス ハッシュです。これらの新機能は非常に好評で、その多くはその後他の Unix シェルにコピーされました。
歴史
履歴機能により、ユーザーは数回のキー入力だけで、以前に実行したコマンドを呼び出して再実行することができます。たとえば、コマンドとして感嘆符 2 つ (" !!") [13]!$を入力すると、直前のコマンドが実行されます。その他の短いキー入力の組み合わせ、たとえば " " (" は " 前のコマンドの最後の引数 " を意味します) を使用すると、以前のコマンドの一部を貼り付けて編集し、新しいコマンドを作成できます。
編集演算子
編集は、前のコマンドのテキストだけでなく、変数の置換でも行うことができます。演算子は、単純な文字列の検索/置換から、パス名を解析して特定のセグメントを抽出するまで多岐にわたります。
エイリアス
エイリアスを使用すると、ユーザーはエイリアスの名前を入力し、C シェルがそれをユーザーが定義した単語のセットに内部的に展開することができます。多くの単純な状況では、エイリアスはスクリプトよりも高速に実行され、便利です。
ディレクトリスタック
ディレクトリスタックを使用すると、ユーザーは現在の作業ディレクトリをプッシュまたはポップできるため、ファイルシステム内のさまざまな場所間を簡単に行き来できるようになります。
チルダ表記
チルダ表記は、 「 」文字を使用してホーム ディレクトリを基準としたパス名を指定する簡単な方法を提供します~。
ファイル名補完
エスケープキーを対話的に使用して、現在のコマンド ラインの末尾にあるファイル名の補完候補を表示できます。
Cdpath
Cdpath は、検索パスの概念を(change directory) コマンドに拡張します。指定されたディレクトリが現在のディレクトリcdにない場合、csh は cdpath ディレクトリ内でそのディレクトリを検索しようとします。
ジョブ制御
1980 年代に入っても、ほとんどのユーザーは複数のウィンドウを使用できない単純なキャラクタ モード ターミナルしか使用していなかったため、一度に 1 つのタスクしか処理できませんでした。C シェルのジョブ制御により、ユーザーは と入力して現在のアクティビティを一時停止し、ジョブと呼ばれる C シェルの新しいインスタンスを作成することができました^Z。その後、ユーザーは コマンドを使用してジョブを切り替えることができましたfg。アクティブなジョブはフォアグラウンドにあると言われました。その他のジョブは一時停止 (停止) されているか、バックグラウンドで実行されていると言われました。
パスハッシュ
パス ハッシュにより、C シェルの実行可能ファイルの検索が高速化されます。ファイルが見つかるか、候補がなくなるまで、各パス ディレクトリでファイル システム コールを 1 つずつ実行するのではなく、C シェルはパス ディレクトリをスキャンして構築された内部ハッシュ テーブルを参照します。通常、このテーブルは、検索せずに C シェルにファイル (存在する場合) の場所を知らせることができ、rehashコマンドで更新できます。
言語の概要
C シェルは、一度に 1 行ずつ処理を行います。各行は、スペースまたは括弧、パイプ、入出力リダイレクト演算子、セミコロン、アンパサンドなどの特別な意味を持つその他の文字で区切られた単語のセットにトークン化されます。
基本的なステートメント
基本的なステートメントは、単にコマンドを実行するものです。最初の単語は、実行するコマンドの名前として取得され、内部コマンド ( などecho) または外部コマンドのいずれかになります。残りの単語は、コマンドに引数として渡されます。
基本的なステートメント レベルでは、文法の特徴は次のとおりです。
ワイルドカード
C シェルは、他の Unix シェルと同様に、ワイルドカード文字を含むコマンドライン引数をパターンとして扱い、一致するすべてのファイル名のリストに置き換えます (グロブを参照)。
*任意の数の文字に一致します。?任意の 1 文字に一致します。[... は]角括弧内の任意の文字と一致します。ハイフンを使用して範囲を指定することもできます。[^...セットに含まれない]任意の文字に一致します。
C シェルは、他の Unix シェルにコピーされたいくつかの表記上の利便性 (拡張グロブと呼ばれることもあります) も導入しました。
abc{def,ghi}は選択(別名、中括弧展開)であり、 abcdef abcghiに展開されます。~現在のユーザーのホームディレクトリを意味します。~userユーザーのホームディレクトリを意味します。
複数のディレクトリ レベルのワイルドカード (例: " */*.c") がサポートされています。
バージョン 6.17.01 以降では、 zshのような再帰ワイルドカード(例: " **/*.c" または " ***/*.html") もglobstarオプションでサポートされます。
ワイルドカードの解釈をシェルに任せることは、Unix では重要な決定でした。つまり、ワイルドカードはすべてのコマンドで、常に同じように機能します。ただし、この決定は、 csh がコマンドを実行するために使用するexecシステム コールを介して長い引数リストを効率的に渡す Unix の機能に依存していました。対照的に、Windowsでは、ワイルドカードの解釈は各アプリケーションによって実行されるのが慣例です。これは、アプリケーションに渡すことができるコマンド ラインが 128 バイトのみであった MS-DOS の遺産であり、DOS コマンド プロンプトによるワイルドカードの使用は非現実的でした。最新のWindows は最大約 32K のUnicode文字のコマンド ラインを渡すことができますが、ワイルドカードの解釈の負担はアプリケーション側にあります。
I/Oリダイレクト
デフォルトでは、 csh がコマンドを実行すると、コマンドはstdin、stdout、stderrの csh の stdio ファイル ハンドルを継承します。これらは通常、 C シェルが実行されているコンソール ウィンドウを指します。I/O リダイレクト演算子を使用すると、コマンドは入力または出力の代わりにファイルを使用できるようになります。
>file は、 stdout がfileに書き込まれることを意味します。存在する場合は上書きされ、存在しない場合は作成されます。エラーは引き続きシェル ウィンドウに表示されます。>&file は、 stdout と stderr の両方がfileに書き込まれ、存在する場合は上書きされ、存在しない場合は作成されます。>>file は、 stdout がファイルの末尾に追加されることを意味します。>>&file は、 stdout と stderr の両方がファイルの末尾に追加されることを意味します。<file はstdin がファイルから読み取られることを意味します。<<文字列はヒアドキュメントです。標準入力は文字列に一致する行まで次の行を読み取ります。
サブシェルの助けがなければ、stderr のみをリダイレクトすることはできません。
set filter = "$home" '/filter'
mkfifo ” $filter "
cat " $filter " & ( ( ls /root/ || echo アクセスできません。 ) > " $filter " ) >& /dev/null
ファイル記述子をファイルとしてサポートするシステムでは、次の回避策を使用できます。
( ( ( echo ok ; '' ) > /dev/fd/0 ) >& /dev/null < /dev/fd/1 ) | ( echo "$<" bye )
接合
コマンドは同じ行に結合できます。
;最初のコマンドを実行してから次のコマンドを実行することを意味します。&&最初のコマンドを実行し、戻りコード0 で成功した場合は次のコマンドを実行することを意味します。||最初のコマンドを実行し、ゼロ以外の戻りコードで失敗した場合は、次のコマンドを実行することを意味します。
配管
コマンドはパイプを使用して接続することができ、これにより、1 つのコマンドの出力が次のコマンドの入力に送られます。両方のコマンドは同時に実行されます。
|stdout を次のコマンドの stdin に接続することを意味します。エラーは引き続きシェル ウィンドウに表示されます。|&stdout と stderr の両方を次のコマンドの stdin に接続することを意味します。
同時実行とは、「並列」という意味です。マルチコア(マルチプロセッサ) システムでは、パイプされたコマンドは文字通り同時に実行される可能性があります。そうでない場合は、オペレーティング システムのスケジューラがそれらのコマンドをタイムスライスします。
コマンド (例: " a | b") が指定されると、シェルはパイプを作成し、 と の両方を起動しaてbstdio をリダイレクトして 2 つのコマンドを起動します。これにより、aは stdout をパイプの入力に書き込み、 はbパイプの出力から stdin を読み取ります。パイプはオペレーティング システムによって一定量のバッファリングとともに実装されるため、aパイプがいっぱいになるまではしばらく書き込みが可能です。ただし、パイプがいっぱいになると、 がb新しい書き込みをブロック解除するのに十分なデータを読み取るまで、新しい書き込みは OS 内でブロックされます。 が使用可能なデータよりも多くのデータを読み取ろうとすると、がさらにデータを書き込むか、パイプが終了するまで ( の場合など)bブロックされます。
aa
変数の置換
単語にドル記号「$」が含まれている場合、後続の文字は変数名として扱われ、参照はその変数の値に置き換えられます。参照の接尾辞として入力されるさまざまな編集演算子により、パス名の編集 (たとえば、:e拡張子のみを抽出するには「 」) やその他の操作が可能になります。
引用とエスケープ
引用メカニズムにより、空白、ワイルドカード、括弧、ドル記号などの特殊文字をリテラルテキストとして扱うことができます。
\次の文字を通常のリテラル文字として扱うことを意味します。"文字列は"弱い引用符です。囲まれた空白とワイルドカードはリテラルとして扱われますが、変数とコマンドの置換は引き続き実行されます。'文字列は'強い引用符です。囲まれた文字列全体がリテラルとして扱われます。
二重引用符内の二重引用符は でエスケープする必要があります。"\""変数の拡張を防ぐため、ドル記号にも同じことが適用されます"\$"。バックティックの場合は、コマンド置換のネストを防ぐために、一重引用符が必要です"'\`'"。
コマンド置換
コマンド置換を使用すると、あるコマンドの出力を別のコマンドの引数として使用できます。
`command は、command`の出力を取得し、それを単語に解析して、コマンド ラインに貼り付けることを意味します。
以下は、 Leaning Toothpick Syndromeによるネストされたコマンド置換の例です 。
echo "`エコー " \"\` "エコー " \"\\\"\\\`\" "エコー " \"\\\"\\\\\\\"\\\\\\\`\ \\"\" "エコー " \"\\\"\\\\\\\"\\\\\\\\\\\\\\"\\\\\\\\\\\\ \\\`\\\\\\\"\\\"\" "エコー " \"\\\"\\\\\\\"\\\\\\\\\\\\\\\ "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`\\\\\\\\\\\\\\\\ \\\\\\"\\\"\" "パスワード" \"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\ \\\\\\\\\\\`\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\`\\\\\\ \\\\\\\\\"\\\\\\\"\\\\\\\`\\\\\\\"\\\"\\\`\\\"\"\` 「」「」
バックグラウンド実行
通常、C シェルはコマンドを開始すると、そのコマンドが終了するまで待機し、その後、ユーザーに新しいコマンドを入力できることを知らせる別のプロンプトを表示します。
- command は、バックグラウンドでコマンドを
&開始し、すぐに新しいコマンドの入力を求めることを意味します。
サブシェル
サブシェルは、シェルの別の子コピーであり、現在の状態を継承しますが、親に影響を与えずに、たとえば現在のディレクトリに変更を加えることができます。
(コマンドはサブシェルでコマンドを)実行することを意味します。
制御構造
C シェルは、条件テストと反復の両方の制御構造を提供します。条件テスト制御構造は、if および switch ステートメントです。反復制御構造は、while、foreach、および repeat ステートメントです。
if文
if ステートメントには 2 つの形式があります。短縮形は 1 行に入力しますが、式が true の場合に 1 つのコマンドのみを指定できます。
if (式)コマンド
長い形式では、then、else、endif キーワードを使用して、条件内にコマンドのブロックをネストできるようにします。
if (式1 ) then
コマンド
else if (式2 ) then
コマンド
...
else
コマンド
endif
else キーワードと if キーワードが同じ行に出現する場合、csh はそれらをネストするのではなく、連鎖します。ブロックは単一の endif で終了します。
switch文
switch ステートメントは、文字列をパターンのリストと比較します。パターンのリストには、ワイルドカード文字が含まれる場合があります。一致するものがない場合、デフォルトのアクション (存在する場合) が実行されます。
switch (文字列)
caseパターン1:
コマンド
breaksw
ケースパターン2:
コマンド
ブレーク
...
デフォルト:
コマンド
区切りsw
終了sw
while文
whileステートメントは式を評価します。式が true の場合、シェルはネストされたコマンドを実行し、式が true である限り繰り返します。
while (式)
コマンド
終わり
foreach ステートメント
foreach ステートメントは、値のリスト (通常はワイルドカードによって生成されたファイル名のリスト) を受け取り、それぞれに対してループ変数をその値に設定し、ネストされたコマンドを実行します。
foreachループ変数(値のリスト)
コマンド
終わり
繰り返し文
repeat ステートメントは、単一のコマンドを整数回繰り返します。
整数コマンド
の繰り返し変数
Cシェルはシェル変数と環境変数の両方を実装しています。[14]ステートメントを使用して作成された環境変数はsetenv常に単純な文字列であり、子プロセスenvp[]に渡され、子プロセスはの引数を介してこれらの変数を取得しますmain()。
setorステートメントを使用して作成されたシェル変数は@、C シェルの内部にあります。子プロセスには渡されません。シェル変数は、単純な文字列または文字列の配列のいずれかになります。一部のシェル変数は定義済みで、ワイルドカードが何にも一致しない場合に何が起こるかなど、さまざまな内部 C シェル オプションを制御するために使用されます。
csh の現在のバージョンでは、文字列の長さは数百万文字まで任意に設定できます。
変数は必要に応じて拡大できます。ただし、固定サイズで作業することが望ましい場合は、次の構文が推奨されます。
# 1024 個の要素を保持できる大きさの変数を作成します。set fixed = { , }{ , } { , } { , } { , }{ , }{ , }{ , }{ , }
表現
C シェルは、C から借用した演算子を使用した 32 ビットの整数式文法を実装していますが、文字列の比較やファイル システム テスト (ファイルの存在のテストなど) 用の演算子もいくつか追加されています。演算子は、そのオペランドから空白で区切る必要があります。変数は$nameとして参照されます。
演算子の優先順位も C から借用したものですが、優先順位が同じ演算子のシーケンスで何が最初に来るかという曖昧さを解決するために、演算子の結合規則が異なります。C では、ほとんどの演算子の結合規則は左から右ですが、C シェルでは右から左です。たとえば、
// C は左からグループ化します
int i = 10 / 5 * 2 ; printf ( " % d \ n " , i ); // 4 が出力されますi = 7 - 4 + 2 ; printf ( "%d \n " , i ); // 5 が出力されますi = 2 >> 1 << 4 ; printf ( "%d \n " , i ); // 16 が出力されます
# C シェルは右からグループ化します
@ i = 10 / 5 * 2
echo $i # 1 を表示します
@ i = 7 - 4 + 2
echo $i # 1 を表示します
@ i = ( 2 >> 1 << 4 )
echo $i # 0 を表示します
C シェルの例の括弧は、ビットシフト演算子が I/O リダイレクト演算子と混同されるのを避けるためのものです。どちらの言語でも、たとえ明確にするためだけの場合でも、括弧を使用して評価の希望する順序を明示的に指定することができます。
戻り値は 8 ビットに制限されます。exit式の場合、単項否定演算子を使用して 32 ビット評価を行うことができます。
exit ! ! 256 # 1 を返します。
受付
スティーブン・ボーン自身も、対話的な使用においてはcshが彼のシェルよりも優れていることを認めていましたが、[ 15]スクリプトではそれほど人気がありませんでした。
1983年には、ベル研究所のライセンスの下で、チャールズリバーデータシステムズのUNOSオペレーティングシステムやその他のUNIXツールとともにcshとBourneシェルの両方が利用可能になりました。[16]
当初から1980年代にかけて、cshはすべてのUnixおよびUnix系システムに存在することが保証されていませんでしたが、shは存在することが保証されていたため、他のマシンで実行する必要があるスクリプトにはより適した選択肢でした。1990年代半ばまでにcshは広く利用可能になりましたが、スクリプトでのcshの使用はPOSIX委員会による新たな批判に直面しました。 [17] POSIX委員会は、対話型およびスクリプトの両方の目的において、推奨されるシェルはKornShellのみであるべきだと規定しました。Cシェルはまた、構文上の欠陥、機能の欠落、実装の貧弱さを理由に 他者からの批判にもさらされました[18] [19] 。
- 構文の欠陥: は、一般的には言語の定義における単純だが不必要な矛盾でした。たとえば、、
setおよびコマンドsetenvはすべて基本的に同じことを行います。つまり、名前を文字列または単語セットに関連付けます。しかし、 3 つすべてにわずかだaliasが不必要な違いがありました。等号は には必要ですがまたは には必要ありません。また、単語リストを括弧で囲む必要があるのは ですがやには必要ありません。同様に、、およびループ構造は、ネストされたブロックを終了するために不必要に異なるキーワード ( 、および) を使用します。setsetenvaliassetsetenvaliasifswitchendifendswend - 不足している機能: 最もよく挙げられるのは、stdioファイル ハンドルを個別に操作する機能と関数のサポートが不足していることです。関数のサポートは不足していますが、エイリアスが回避策として機能します。コードが複数行の場合、エイリアスは一重引用符で囲む必要があり、各行の末尾はバックスラッシュの前になければなりません (最後の行の末尾は、エイリアスの末尾を区切るために一重引用符の前になければなりません)。関数の回避策としては、スクリプト内のエイリアスよりも再帰の方が適しています (以下に例を示します)。
- アドホックパーサーを使用した実装は、最も厳しい批判を浴びました。1970年代初頭までに、コンパイラ技術は十分に成熟し[20] 、ほとんどの新しい言語実装では、完全に再帰的な文法を認識できるトップダウンまたはボトムアップパーサーが使用されました。Cシェルにアドホック設計が選択された理由は不明です。ジョイが2009年のインタビューで述べたように、「Unixでこの作業を始めたとき、私はあまり良いプログラマではありませんでした。」[21]というだけのことかもしれません。アドホック設計は、Cシェル言語が完全に再帰的ではないことを意味していました。処理できるコマンドの複雑さには限界がありました。
これは、対話的に入力されるほとんどのコマンドでは機能しましたが、ユーザーがスクリプトに記述するより複雑なコマンドでは、簡単に失敗し、不可解なエラー メッセージや望ましくない結果しか生成されませんでした。たとえば、C シェルは制御構造間のパイプをサポートできませんでした。コマンドの出力foreachを にパイプしようgrepとしても、うまくいきませんでした。(パーサーに関連する多くの苦情に有効な回避策は、コードを別のスクリプトに分割することです。 を別foreachのスクリプトに移動すると、正しい stdio ハンドルを継承する csh の新しいコピーをフォークしてスクリプトが実行されるため、パイプが機能します。単一ファイル内のコードを分割することもできます。単一ファイル内のコードを分割する方法の例を次に示します。)
もう 1 つの例は、次のフラグメントの望ましくない動作です。これらは両方とも、「'myfile' が存在しない場合は、'mytext' を書き込んで作成する」という意味のように見えます。ただし、右側のバージョンでは常に空のファイルが作成されます。これは、C シェルの評価順序が、各コマンド ラインを読み込むときに I/O リダイレクト演算子を探して評価し、その後、ラインの残りの部分を調べて制御構造が含まれているかどうかを確認することになっているためです。
# 期待通りに動作します
if ( ! -e myfile ) then echo mytext > myfile
終了
# 常に空のファイルを作成します
if ( ! -e myfile ) echo mytext > myfile
# 回避策 (tcsh のみ)
if ( ! -e myfile ) eval "echo mytext > myfile"
# 2 番目の回避策 (csh および tcsh の場合)
( exit ( -e myfile ) && ( ( echo mytext > myfile ) >& /dev/null || echoファイルを作成できません。) || echoファイルが存在します。
この実装は、たとえば「0: イベントが見つかりません。」など、問題に関する有用な情報をまったく提供しない、非常に質の悪いエラー メッセージについても批判されています。
ただし、練習することで、これらの欠陥を克服することができます (これにより、プログラマーはスクリプトを実装する際に、より適切で安全なアプローチを取るように指示されます)。
「0: イベントが見つかりません。」というエラーは、履歴に保存されたコマンドがないことを意味します。履歴はスクリプトでは正しく機能しない可能性がありますが、変数にコマンドの事前設定があると回避策として機能します。
#!/bin/csh -f
set cmdlist = ( 'date # 1' \
'uname # 2' \
'tty # 3' \
'id # 4' )
echo -n '履歴からコマンドを実行するには番号を入力してください: '
set cmdexec = "$<"
( exit ( ! ( "$cmdexec" > 0 && \
"$cmdexec" < = "$#cmdlist" ) ) ) >& /dev/null
if ( "$status" ) then
echo 'イベント番号が無効です。' foreach cmd ( $cmdlist :q ) echo "$cmd" end exit -1
endif eval "$cmdlist[$cmdexec]"
関数の回避策として、スクリプトを再帰的に実行してコードを分割することを優先します。
#!/bin/csh -f
if ( ! "$?main" ) then
if ( ! "$?0" ) then
echo 'このスクリプトは、明示的にファイルを呼び出して実行する必要があります。' exit -1
endif alias function 'set argv = ( \!* ) ; source "$main"' set main = "$0" set ret = "`function myfunc`" echo "$ret" exit endif
"$1" に移動; シフト
私の機能:
関数 myfunc2
echo "関数です。"
exit
myfunc2:
echo "別の関数です。"
exit
影響

C シェルは、履歴メカニズム、エイリアス、チルダ表記、対話型ファイル名補完、シェルに組み込まれた式文法など、多数の革新的機能を導入することに非常に成功しました。これらの革新的機能は、その後、他の Unix シェルによって模倣されました。しかし、kshやbashなど、多数の独自開発のクローンを生み出したshとは対照的に、 cshクローンは2 つしか知られていません ( tcsh は、Bill Joy によって最初に書かれた csh コードに基づいているため、クローンとは見なされません)。
1986年、アレン・ホルブはOn Command: Writing a Unix-Like Shell for MS-DOSを執筆した。[22]この本は彼が書いた「SH」というプログラムについて記述しているが、実際にはshではなくcshの言語設計と機能をコピーしたものである。SHの完全なソースとUnix風ユーティリティの基本セット(cat、cp、grepなど)を含む付属ディスケットは、それぞれ25ドルと30ドルで出版社から入手できた。ホルブのSHの制御構造、式の文法、履歴メカニズム、その他の機能はCシェルのものと同一であった。
1988年、ハミルトン研究所はOS/2用のHamilton C shellの出荷を開始しました。[23]これにはcshクローンとUnixライクなユーティリティのセットが含まれていました。1992年、Hamilton C shellがWindows NT用にリリースされました。[24] Windowsバージョンは引き続き積極的にサポートされていますが、OS/2バージョンは2003年に廃止されました。[24] 1990年初頭のクイックリファレンス[25]では、その意図は「C shell言語全体に完全に準拠(ジョブ制御を除く)する」と説明されていますが、言語設計の改善とUnixとPCの違いへの適応が図られています。最も重要な改善点は、制御構造のネストやパイプを可能にするトップダウンパーサーでした。これは、アドホックパーサーのため、オリジナルのC shellではサポートできませんでした。Hamiltonでは、組み込みおよびユーザー定義のプロシージャ、ブロック構造のローカル変数、浮動小数点演算などの新しい言語機能も追加されました。 PC への適応には、PC 上のファイル名やその他の規則のサポート、およびパイプラインの設定などで並列処理を実現するためにフォーク(OS/2 や Windows では利用できなかった)の代わりにスレッドを使用することが含まれていました。
参照
参考文献
- ^ Zoulas, Christos (2016年11月24日). 「tcsh-6.20.00 が利用可能になりました!」mx.gw.com。 2016年11月25日時点のオリジナルよりアーカイブ。2016年11月24日閲覧。
- ^ Harley Hahn、「Harley Hahn's Guide to Unix and Linux」Wayback Machineに 2019 年 8 月 24 日にアーカイブ。
- ^ Berkeley Engineering Lab Notes、第1巻第2号、2001年10月、Wayback Machineで2010年7月9日にアーカイブ。
- ^ C シェル入門、Bill Joy著、Wayback Machineに 2018 年 7 月 13 日にアーカイブ。
- ^ Ubuntu - パッケージ csh の詳細。Packages.ubuntu.com。
- ^ Debian - パッケージ csh の詳細。Packages.debian.org。
- ^ Ubuntu - パッケージ tcsh の詳細。Packages.ubuntu.com。
- ^ Debian - パッケージ tcsh の詳細。Packages.debian.org。
- ^ Ken Greer (1983 年 10 月 3 日)。「コマンドとファイル名の認識/補完機能を備えた C シェル」。ニュースグループ: net.sources。2010年12 月 29 日閲覧。
- ^ tcsh(1) マニュアルページ。tcsh。
- ^ 2000 年 6 月の tcsh-17 でファイルを修正しました。
- ^ Re: Late Bloomers Revisited USENET 投稿、comp.lang.misc、Piercarlo "Peter" Grandi、UCW Aberystwyth、英国、1989 年 12 月 17 日。
- ^ 「バン、バン」と発音します
- ^ Troy, Douglas (1990) 。UNIX システム. コンピューティングの基礎。Benjamin/Cumming Publishing Company。p. 25。
- ^ Bourne, Stephen R. (1983 年 10 月). 「The Unix Shell」. BYTE . p. 187. 2015 年1 月 30 日閲覧。
- ^ The Insider's Guide To The Universe (PDF) . Charles River Data Systems, Inc. 1983. p. 13.
- ^ IEEE 情報技術標準、ポータブル オペレーティング システム インターフェイス (POSIX)、パート 2: シェルとユーティリティ、第 2 巻。IEEE Std 1003.2-1992、pp. 766-767。ISBN 1-55937-255-9。
- ^ Csh プログラミングは有害であると考えられる (Tom Christiansen 著)
- ^ C シェルを使わない 10 の理由 (Bruce Barnett 著)
- ^ David Gries (1971). Compiler Construction for Digital Computers. John Wiley & Sons. ISBN 0-471-32776-X .
- ^ ビル・ジョイがブレント・シュレンダーと対談、チャーチル・クラブ、カリフォルニア州サンタクララ、2009年2月11日[盗用]。
- ^ ホルブ、アレン(1986–1987)。『On Command: MS-DOS 用 Unix 風シェルの作成(第 2 版)』。M&T Books、カリフォルニア州レッドウッドシティ。ISBN 0-934375-29-1。
- ^ ハミルトン、ダグラス。「ハミルトン C シェルの発表」(PDF)。IBMパーソナル システム開発者(1989 年夏): 119–121。2020年7 月 11 日閲覧。
- ^ ab Hamilton, Nicole (2017 年 3 月 5 日). 「Hamilton C shell for Windows リリース ノート 5.2.g」. Hamilton Laboratories、ワシントン州レドモンド。2018年4 月 3 日閲覧。
- ^ Hamilton C シェル クイックリファレンス(PDF) . Hamilton Laboratories、マサチューセッツ州ウェイランド。1988–1990 . 2020 年7 月 11 日閲覧。
さらに読む
- アンダーソン、ゲイル、ポール・アンダーソン (1986)。UNIX C シェル フィールド ガイド。Prentice- Hall。ISBN 0-13-937468-X。
- ポール・ワン (1988)。『Berkeley UNIX 入門』。ワズワース出版。ISBN 0-534-08862-7。
- DuBois, Paul (1995)。csh と tcsh の使用。O'Reilly & Associates。ISBN 1-56592-132-1。
- Arick, Martin R. (1993). UNIX C Shell デスクリファレンス. John Wiley & Sons. ISBN 0-471-55680-7。
- 「C シェルプログラミング入門」。カニシウス大学コンピュータサイエンス学部。2010年6 月 23 日閲覧。
外部リンク
- William Joyによる C シェル入門。
- Linux を簡単に説明すると: 第 8 章 csh と tcsh。
- tcsh ホームページ。
- tcsh(1)のマニュアルページ。
- 入手可能な最新の tcsh ソース コード。
- 1980 年 2 月 2 日付の歴史的な 2BSD csh ソース コード。
- Unix ツリー、完全な歴史的な Unix ディストリビューション。
- Csh プログラミングは有害であると考えられます。
- C シェルを使用しない 10 の理由。
