1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

awkでオプション解析(getopts相当の実装)

Last updated at Posted at 2024-08-19

はじめに

awk でオプション解析を行いたかったのでシェルの getopts 相当の機能を持つ関数を実装しました。ロングオプションなどには対応していません。gawk だけではなく POSIX に準拠したどの awk の実装でも動作します。

awk 版 getopts の実装

getopts という関数名にしていますが、シェルの getopts コマンド互換のインターフェースにするつもりはありません。

function getopts(optstring, args,  i, j) {
  i = OPTIND ? int(OPTIND) : (OPTIND = 1)
  j = int(substr(OPTIND, length(i) + 2))
  OPTERR = OPTARG = ""
  if (!(i in args)) return 0
  if (args[i] == "--") { OPTIND = i + 1; return 0 }
  if (args[i] !~ /^-./) return 0
  OPT = substr(args[i], j + 2, 1)
  OPTARG = substr(args[i], j + 3)
  if (index(optstring, OPT ":")) {
    if (OPTARG == "") {
      if (!(++i in args)) {
        OPTERR = "option requires an argument -- " OPT
        OPTARG = ":"
        return 0
      }
      OPTARG = args[i]
    }
    OPTIND = i + 1
  } else if (OPT != ":" && index(optstring, OPT)) {
    OPTIND = (OPTARG == "") ? (i + 1) : (i "," (j + 1))
  } else {
    OPTERR = "illegal option -- " OPT
    OPTARG = "?"
    return 0
  }
  return 1
}

使い方

上記の関数を awk スクリプトの冒頭に埋め込んだりして実行してください。以下はシェルスクリプトに埋め込んだ場合のサンプルコードです。

#!/bin/sh

${AWK:-awk} "$(cat getopts.awk)"'
  BEGIN {
    while(getopts("fgo:p:", ARGV)) {
      if (OPT == "f") print OPT
      if (OPT == "g") print OPT
      if (OPT == "o") print OPT " : " OPTARG
      if (OPT == "p") print OPT " : " OPTARG
    }
    if (OPTERR) {
      printf "%s (OPT: %s, OPTARG: %s)\n", OPTERR, OPT, OPTARG
      exit 1
    }
    print "Arguments:"
    for (i = OPTIND; i < ARGC; i++) {
      print ARGV[i]
    }
  }' "$@"

以下のグローバル変数を使用します。

  • OPTIND 次にオプションを解析する引数位置
    • 新しいオプション解析を始める時は1に設定すること
  • OPT 読み込んだオプション
  • OPTARG オプション引数(存在する場合)
  • OPTERR エラー時のメッセージ

getopts はオプション解析の終了またはエラー時に偽を返します。エラー時には OPTRERR にエラーメッセージを OPTARG にエラーの種別を設定します。

  • OPTARG エラーの種別
    • ? 不正なオプション
    • : オプション引数が必要な場面で、オプション引数が存在しない場合

その他の実装

gawk でも getopt.awk という同等の処理を行う関数が Public Domain で提供されています。こちらはロングオプションにも対応しているようです。

ロングオプション対応を除いて機能的には大差ないのですが、少々使い方やコードが冗長に感じたので再実装しています。

さいごに

このコードのライセンスは今のところ特に指定していませんが自由に使用してください。リポジトリを以下にあります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?