ラベル echo の投稿を表示しています。 すべての投稿を表示
ラベル echo の投稿を表示しています。 すべての投稿を表示

2015年7月8日水曜日

Posted by mattintosh | File under : , , , , ,
最初の方に書いておくべきでしたが変数などのお話です。

「変数とはなにか?」についてはここでは詳しくお話しません(ウェブ上にたくさん情報があるので検索してみてください)。

変数の型

C 言語などでは変数には「型」を指定する必要がありますが、bash の変数は何でも入ります(nul は入らなかったと思いますが)。

そんな何でもアリな bash の変数ですが、declare を使うことで整数値として宣言することができます。 declare -i で宣言しているものは英字を入れても 0 になります(※記号などを代入しようとするとエラーになります)。

変数展開時の {} って必要?

これまでのスクリプトではすべて ${PATH} のように {}(ブレース⁄brace)を記述してきましたが、$PATH と書いても問題はありません。私はスクリプトではできるだ書くようにしていますが、対話モードでは必要なときだけつけています。

ブレースが必要になるパターンをいくつかお話します。

変数名の区切りとして

{} が必要なとき」というのは下の実行結果を見てみてください。 変数名にブレースがない場合は「$ から変数名として使える文字が終わるところまで」が変数名になります。3行目と5行目を見比べてみるとわかりますが、ブレースを使うことで「どこからどこまでが変数名なのか?」を指定することができます。

7行目のような書き方でも展開はできますがあまりこういった書き方はしません(私はですが)。

8行目ではブレースなしでも $BASH が正しく展開されていますが、$BASH.VERSION という変数は存在しない(というか . があるので宣言できない)ので $BASH という変数と .VERSION という文字列として認識されます。

よくある間違いは変数と _ を使って文字を連結する場合です。なぜ _ の方だけ $BASH 部分が展開されていないかはもうわかりますね?

配列の展開のために

BASH_VERSINFO は bash のバージョン情報が入った配列変数です。 BASH_VERSINFO をブレースありとなしで出力してみます。 ブレースなしの方は $BASH_VERSINFO という変数と [〈インデックス〉] という文字列として認識されます。 今度は for を使ってインデックスを変数から展開します。 先程と同じくブレースなしの方は正しく展開されていません。また、ブレース内の [〈変数〉]$ を付けなくても展開されていますが、ブレースなしの方はそちらも展開されていません。 配列変数を展開するにはブレースが必要になります(※0番目の要素は除く)。$BASH_VERSINFO[0] と書いたものは ${BASH_VERSINFO}[0] と書いたときと同じ認識になってるんですね。

置換展開のため

bash を含め、いくつかのシェルではブレースを使った変数展開の際に、特殊な展開を行うことができます。 シェルのコマンドには Ruby などにある拡張子だけを取り出す extname() のようなものがありません(知らないだけかもしれませんが)。ですが、上記のような置換展開を使うことで cut や sed のようなコマンドに頼らず拡張子だけを取り出すことができます。
ブレースが必要になるパターンというのはおわかりいただけたでしょうか?私は「後で書くくらいなら最初から書いておく」タイプなので書いてますが、先に述べたようにブレースなしでも動くものは動きます。

変数に関することはまだまだたくさんあるのですが、長くなってしまったので今回はこの辺で終わりにしたいと思います。

最後にお遊びスクリプトとして画像ファイルを一括で JPEG に変換するスクリプトを紹介します。convert は ImageMagick に含まれている画像変換プログラムです。

case を併用することで拡張子がついているかどうかをより正確に判断できるようになります。

休みの日にだらだらと書いてしまったので説明の順序がごちゃごちゃになってしまいました。ごめんなさい。

ではまたそのうちお会いしましょう(・∀・)ノシ

2015年6月23日火曜日

Posted by mattintosh | File under : , , , , ,
前回、typedeclare というコマンドを使いました。これらは bash に含まれる内蔵(組み込み)コマンドです。「内蔵」というからには「外部」もあるのですが、lscat など、その他多くのコマンドが外部コマンドです。

内蔵コマンドは enable コマンドや help コマンド、man bashman bash-builtins で確認することができます。 前回のコマンド検索では type を使いましたが、実際にコマンド検索でよく使われるのは which です。なぜ which ではなく type を使ったかというのは以下のスクリプトを実行してみてください。 このコマンドの結果は以下のようになります。 どちらも unset PATH した後にエラーが出ていますが、エラーの内容が異なります。type の方は「ls コマンドが見つからない」と出ていますが、which の方は「そのようなファイルやディレクトリはない」と出ています。これは which が外部コマンドなので unset PATH すると、コマンド名だけでは呼び出しができず、which を実行ができないからです。前回、type を使ったのはそのためです(which にすらパスが通ってない環境ではあまり意味がありませんが)。

type は引数に指定されたコマンドがシェルのエイリアスや関数であればその内容を表示します(これはオプションによって変わります)が、which は外部コマンドのみを探すという違いもあります。

内蔵コマンドと外部コマンドの特徴

内蔵コマンドと外部コマンドの特徴を以下に挙げます。

内蔵コマンドの特徴

  • 外部コマンドより速い
  • PATH に依存しない
  • bash 独自のコマンドがあるため他のシェルで使えない可能性がある(例:ksh で declare は使えない)
  • バージョンによって実装されていないコマンドやオプションがある(例:readarray などは bash 3.2 では使えない)

外部コマンドの特徴

  • 内蔵コマンドより遅い
  • PATH に依存する(※ファイル名のみで呼び出す場合)
  • バージョンやシェルの種類が異なっても同じ動作が期待できる(オプションの種類など)
内蔵コマンドと外部コマンドの両方にメリット・デメリットがあります。プロジェクトなどのルールで実行シェルが bash と決まっているのであれば内蔵コマンドでもいいと思います(ただ、bash に限定してスクリプトを書くことはほとんどないと思います…)。

速度の違い

以下は内蔵コマンドと外部コマンドの速度を比較するためのスクリプトです。 内蔵コマンドの方は0秒未満で終了していますが、外部コマンドの方は16秒近くかかりました。

オプションの違い

Lesson 2 で echo を作ったスクリプトの話をしましたが、「意図しない結果が出力されている部分がある」と話したのを覚えているでしょうか? すでにおわかりだと思いますが、スクリプト内にコメントとして書いていたものは外部コマンドの方の echo の書式です。内蔵の echo はロングオプション(--help--version)を受け付けません。help echoman echo で比較してみてください。
# 内蔵 echo の書式
echo [-neE] [arg ...]

# 外部 echo の書式
echo [SHORT-OPTION]... [STRING]...
echo LONG-OPTION

enable も使ったサンプルを置いておきますのでご自由にお試しください。 which の他に whereis というコマンドもありますのでそちらもチェックしてみてください。

2015年6月22日月曜日

Posted by mattintosh | File under : , ,
特にお題がない ヽ(´ー`)ノ


まずはスクリプトを書いてみましょう。

テキストエディタで以下のようなスクリプトを作成してみてください。ファイル名は「sample.txt」とし、ファイルの保存場所はホームディレクトリとします。
スクリプトを保存したら、ターミナル上で chmod コマンドで実行権限を付与します。
vi を使っている場合は :!chmod +x % で vi を終了せずに実行権限を付与できます。Komodo Edit を使っている場合は Ctrl + R でコマンド実行画面を呼び出せます。%F は現在のファイルのフルパスに置き換えられます。
statls -l でファイルを確認してみましょう。実行権限が付与されていることを確認してください。
~/sample.sh を実行します。 うまくメッセージが表示されたでしょうか?

では先程のファイルにいくつか記述を追加してみます。 変更点は以下の差分を確認してください。先頭に + がついている行が追加された行です。いずれこの差分の見方も紹介します。 実行権限は既に付与されているのでそのまま先程と同じように実行します。先程の出力よりかなり多くなっていますが、ところどころに出力されている >>> 部分に注目してみてください。 所々にスクリプトに書いてあるコマンドが出力されているのがわかるでしょうか?これは bash の xtrace オプション(set -x)によるものです。デバッグなどに使ったりするオプションですが、練習用におおすすめです。無効にする場合は set +x のようにオプションの符号を反転させます。

xtrace オプションを有効にするには、上記のスクリプトのように有効にしたいところに set -x または set -o xtrace を記述します。また、シェバングに #!/bin/bash -x を記述しても有効にすることができます。シェバングに記述する方がシンプルですが、無効にする場合にいちいち削除しなくてはいけないので set -x がおすすめです。

xtrace の有効・無効確認用のスクリプトです。 実行結果は下記のようになります。
スクリプトを書いて実行するところまではできたでしょうか?なお、xtrace はスクリプト内だけではなくターミナル上でも使うことができます。似たような機能で set -v もありますが、xtrace の方がコマンドの出力や引数がわかりやすくなっています。

実は今回作成したスクリプトには意図しない結果が出力されている部分があるのですがそれはまた今度お話します。