Help us understand the problem. What is going on with this article?

Bashの括弧のノウハウ(まとめ)

すでにQiitaにもいくつか記事があるが 1、Bashでの各種の括弧はそれぞれ意味がある。
自分でも知らなかったBashの括弧もあったので、改めてまとめてみた。

なお、Bashの話ではあるが、Shell(/bin/sh)としても動くサンプルコードは sh コードとしてある。

bracket [ ]

Shからある伝統的なコマンドで、test と等価。式の結果を、0が真、1が偽の真偽値で返す。
if と組み合わせて用いることが多い。
[] の前後にはスペースが必要で、後続のコマンドがある場合は;で終わらせなければならない。なぜなら [はコマンドだからで、[ から ] までが一連のコマンドと引数の組み合わせだからだ。(]は必須な引数)

sh
if [ "x$1" = "x--help" -o "x$1" = "x-h" ]; then
  show_help    # help
fi

この場合の式で "x$1" のように x といれている(何の文字列でもいい)のは、例えば$1が空文字列だった場合にエラーになるから。先人の工夫である。

なお、論理式は-a-oを使う方法の他に、&&||を使って表現することも可能。
ただ前者は優先順位はあるのだが、後者の場合はコマンドとして順に処理されるので優先順位がない。

sh
if [ "x$OPT" = "x-h" -o "x$OPT" = "x--help" ]; then
  help
fi
if [ "x$OPT" = "x-h" ] || [ "x$OPT" = "x--help" ]; then
  help
fi
# if を無くした形
[ "x$OPT" = "x-h" ] || [ "x$OPT" = "x-h" ] && help

double bracket [[ ]]

Bashになって 2 追加された条件式で、[ ]の機能が拡張されたもの。
返す真偽値は同じだが、次の様な機能が追加されている。

bash
( <EXPRESSION> )                    式のグループ化。優先される。
<EXPRESSION1> && <EXPRESSION2>      論理積。なお、従来の `-a` は使ってはいけない。
<EXPRESSION1> || <EXPRESSION2>      論理和。なお、従来の `-o` は使ってはいけない。
! <EXPRESSION1>                     論理否定。
<STRING> == <PATTERN>               文字列比較。
<STRING> = <PATTERN>                == と同じ。
<STRING> != <PATTERN>               文字列比較でマッチしていない場合に真。
<STRING> =~ <ERE>                   拡張正規表現による文字列比較。

なお、正規表現を含む文字列比較は、[ ]と違って式中で対象文字列を""で囲まなくてよい 3が、Shellにより解釈されて意図しない文字列に変換される可能性がある。なので、直接[[ ]]中に正規表現を書くのではなく、変数を用いて比較すると良いだろう。

bash
REGEXP="[hc]at"
[[ cat =~ $REGEXP ]] && echo "Matched"

parentheses ( )

サブシェル

丸かっこは、サブシェルで記述されたコマンドまたはコマンド群を実行する。
Shからの機能である。

sh
pwd
( cd /usr; pwd )
pwd       # 最初の結果と同じ 

コマンド実行

Shで ` ` で実現していたコマンド実行を、 Bashでは $() で表すことができる。

bash
SEED=$(expr $(date +%M) + $(date +%S))
echo $SEED

echo `date '+%Y/%m/%d'`        # Sh 方式も使える

関数

関数を宣言する場合に、関数名に()をつけて宣言する。

sh
funcname() {
    local FUGA
    set -- $*
    HOGE=$1
    FUGA=$2    # FUGA はローカル変数
}

# Call
funcname
funcname "hoge" "fuga"

double parentheses (( ))

算術演算を表す。Cの形式の演算が使えたり4と、いろいろな式が使える。

bash
echo $(( 0x10 ))             # 16
echo $(( (2+3) * 5 / 2 ))    # 12. 小数は表せない

if の式として使えるが、[ ] による式と違って、値が0の時に偽値となる。

bash
if ((0)); then
  echo "true"
else
  echo "false"
fi
# "false"

Cのようなforループも、表すことが可能。

bash
for ((x=1; x<=3; x++))
{
  echo $x
}
# Bash では、 do~done の代わりに、{~} が使える

braces { }

変数展開

変数名と文字列を区別する時に、変数名を明示的に指し示すために使う。

sh
STR="user_${NAME}_logged_in!"

2桁以上の位置パラメータを表す時にも使う。

sh
$ piyopiyo.sh "hoge" "fuga" 3 4 5 6 7 8 9 ten eleven
# $1    => hoge
# ${10} => ten

Bash独自の便利な変数展開もある。こちらの記事にまとめられている。

bash
echo $HOGE            # (null)
echo ${HOGE:-hoge}    # hoge    ... just behalf
echo $HOGE            # (null)

echo $FUGA            # (null)
echo ${FUGA:=fuga}    # fuga
echo $FUGA            # fuga    ... also substituting value as deafult

コマンド群の実行

() がサブシェルでコマンドを実行するのに対し、カレントシェルで(ブロック処理のように)一連のプログラムを実行できる。
出力内容は、纏めてリダイレクトなどが可能。

sh
{
  echo "PASSWD follows"
  cat /etc/passwd
  echo
  echo "GROUPS follows"
  cat /etc/group
} >output.txt

シンプルな例としては、関数での使用例。

sh
help() {
    echo "Usage: $0 [-h|--help]"
    exit 255
}

ここに乗っていた Try-Catch ブロックの例。

sh
try_catch() {
    { # Try-block:
        eval "$@"
    } ||
    { # Catch-block:
        echo "An error occurred"
        return -1
    }
}

参考

ここのサイトが大変参考になった!

Bash Hackers Wiki - http://wiki.bash-hackers.org/start


  1. https://qiita.com/yohm/items/3527d517768402efbcb6 

  2. BashはBourne Again Shellで、Bourne Shell(いわゆるsh)から拡張されたシェルである。 

  3. [a-z]など、ローケルに少なからず影響されるので、POSIXクラスを使うと良いだろう。 (cf; https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE#%E6%A8%99%E6%BA%96 ) 

  4. http://wiki.bash-hackers.org/syntax/arith_expr 

Ping
都内勤務のSEでやんす。ポエ~
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。東京(三軒茶屋)/京都(四条烏丸)/札幌/大阪/福岡に展開中!Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした