TT Lab
はじめる
学ぶ 学習パス コース

シェルスクリプティング

繰り返しと関数

TT Labで続きを見る

目標

繰り返しと関数を、実際に使える形で身につけます。特に、「一致するファイルがないとき」、「引数に空白があるとき」、「引数がまったくないとき」のような境界の状況で、壊れないように作ります。

なぜ重要なのか

シェル関数は値を返しません。計算した値は標準出力に出し、成功と失敗は終了コードで知らせます。この規約を守ってこそ、if is_number "$x"のような自然な使い方ができます。そして、ファイルの一覧はlsをパースせず、シェルのグロブに任せます。$(ls *.log)は空白を含むファイル名で壊れ、一致がないときにエラーメッセージをループの入力として流し込みます。代わりにグロブを使うと、一致がないときにパターン文字列がそのまま残るという別の落とし穴が生まれるので、[ -f "$f" ] || continueという防御線が必要です。

ステップ

  1. /root/bin/loop1.shを作り、1から5まで1行に1つずつ出力させてください。
  2. /root/loops/logsディレクトリを作り、その中に.logファイルを4つ、.txtファイルを2つ置いてください。そして/root/bin/count.sh <디렉터리>を作り、そのディレクトリの直下の.logファイルの個数だけを出力させてください(プレースホルダーはディレクトリです)。空のディレクトリを渡すと0が出る必要があります。
  3. /root/loops/users.csvに이름,역할の形式で3行以上入れ、/root/bin/readcsv.shを作って、そのファイルを読んで이름(역할)の形式で1行ずつ出力させてください(引数なしで実行します。2つの形式の韓国語は、それぞれ「名前」と「役割」を意味する語です)。
  4. /root/bin/lib.shにslugify関数を定義してください。単語を小文字に変えて、ハイフンでつなぎます。/root/bin/use.shは、そのファイルをsourceで読み込んで使う必要があります。use.sh Hello Worldの出力はhello-worldです。
  5. /root/bin/isnum.sh <문자열>を作ってください。数字だけでできていれば終了コード0、そうでなければ0以外のコードです。何も出力してはいけません。空文字列、符号、小数点は、すべて数字ではありません(プレースホルダーは文字列です)。
  6. /root/bin/each.shを作り、受け取った引数ごとに[인자]の形式で1行ずつ出力させてください。each.sh "a b" cは2行になる必要があります。引数がなければ何も出力しません(プレースホルダーは引数です)。
  7. /root/bin/sum.shを作り、受け取った数値の引数の合計を出力させてください。引数がなければ0です。
  8. /root/bin/summary.sh <디렉터리>を作ってください。そのディレクトリの.logファイルの個数と全体の行数を、次の2行で出力します(プレースホルダーは、ディレクトリ、個数、合計です)。
    • files=<개수>
    • total_lines=<합계>

参考

1から5までを出力する

/root/bin/loop1.shを作り、1から5まで1行に1つずつ出力させてください。

for x in 1 2 3 4 5、またはブレース展開{1..5}を使えます。

グロブでファイルを数える

/root/loops/logsディレクトリを作り、その中に.logファイルを4つ、.txtファイルを2つ置いてください。そして/root/bin/count.sh <디렉터리>を作り、そのディレクトリの直下の.logファイルの個数だけを出力させてください(プレースホルダーはディレクトリです)。空のディレクトリを渡すと0が出る必要があります。

一致するファイルがないと、パターン文字列がそのまま残ります。[ -f "$f" ] || continueで除外してください。

CSVを1行ずつ読む

/root/loops/users.csvに이름,역할の形式で3行以上入れ、/root/bin/readcsv.shを作って、そのファイルを読んで이름(역할)の形式で1行ずつ出力させてください(引数なしで実行します。2つの形式の韓国語は、それぞれ「名前」と「役割」を意味する語です)。

while IFS=, read -r a bの形を使い、入力はdoneの後ろでリダイレクトします。

関数をライブラリとして分離する

/root/bin/lib.shにslugify関数を定義してください。単語を小文字に変えて、ハイフンでつなぎます。/root/bin/use.shは、そのファイルをsourceで読み込んで使う必要があります。use.sh Hello Worldの出力はhello-worldです。

関数をlib.shに定義し、use.shから.またはsourceで読み込んでください。コピペしてはいけません。

終了コードで判定する

/root/bin/isnum.sh <문자열>を作ってください。数字だけでできていれば終了コード0、そうでなければ0以外のコードです。何も出力してはいけません。空文字列、符号、小数点は、すべて数字ではありません(プレースホルダーは文字列です)。

判定結果を出力すると、if文で使えません。return 0 / return 1でのみ知らせてください。

空白を含む引数を安全に巡回する

/root/bin/each.shを作り、受け取った引数ごとに[인자]の形式で1行ずつ出力させてください。each.sh "a b" cは2行になる必要があります。引数がなければ何も出力しません(プレースホルダーは引数です)。

for x in "$@"とfor x in $*の違いを確認してください。引数がないときは、何もしない必要があります。

可変長引数の合計

/root/bin/sum.shを作り、受け取った数値の引数の合計を出力させてください。引数がなければ0です。

累積変数を0で初期化するのを忘れないでください。引数がなければ0が出る必要があります。

ディレクトリの要約レポート

/root/bin/summary.sh <디렉터리>を作ってください。そのディレクトリの.logファイルの個数と全体の行数を、次の2行で出力します(プレースホルダーは、ディレクトリ、個数、合計です)。

ファイルの個数と全体の行数を一緒に数えます。空のディレクトリでも0/0が出る必要があります。