LoginSignup
4
3

More than 1 year has passed since last update.

シェルスクリプトの世界から基本正規表現(BRE)をなくそう!

Posted at

はじめに

UNIX コマンドが対応している正規表現には、基本正規表現 (BRE) と拡張正規表現 (ERE) の二種類があります。誰もがよく知っている正規表現は拡張正規表現(の拡張版)です。基本的には基本正規表現はもう忘れていいです。ならぜなら、一番の懸念点であった sed コマンドの拡張正規表現対応 (sed -E) が POSIX Issue 8 で標準化されることになったからです。

シェルスクリプトでよく使う awk、grep、sed が拡張正規表現に対応したことで、基本正規表現はほぼ不要になりました。拡張正規表現に対応していないのは、あまり必要でない expr や、シェルスクリプトでほとんど使われない ed、ex、more ぐらいです。

とはいえ expr で基本正規表現は使うと言えば使います。で、ふと思ったのですが、基本正規表現と拡張正規表現はエスケープする文字が異なるだけで機能はほとんど同じです(下記参考リンク参照)。それなら拡張正規表現を基本正規表現に変換してやれば、基本正規表現を使う必要はないですよね?ということで実装してみました。これでもう基本正規表現のことは忘れてしまうことが出来ます。

参考リンク

実装(サンプル)

注意 思いつきでざっくり実装しただけのでテストは不十分です。バグがあるかもしれません。

#!/bin/sh

set -eu

# 拡張正規表現(ERE)から基本正規表現(BRE)への変換関数
ere2bre() {
  set -- "$1" "$2" ""
  while [ "$2" ]; do
    case $2 in
      "\\+"* | "\\?"* | "\\|"* | "\\{"* | "\\}"* | "\\("* | "\\)"*)
        set -- "$1" "${2#?}" "$3"
        set -- "$1" "${2#?}" "$3${2%"${2#?}"}"
        ;;
      "+"* | "?"* | "|"* | "{"* | "}"* | "("* | ")"*)
        set -- "$1" "${2#?}" "$3\\${2%"${2#?}"}"
        ;;
      *) set -- "$1" "${2#?}" "$3${2%"${2#?}"}" ;;
    esac
  done
  eval "$1=\$3"
}

# 拡張正規表現対応させるための expr のラッパー
expr() {
  if [ "${2:-}" = ":" ]; then
    ere2bre bre "$3"
    set -- "$1" "$2" "$bre"
  fi
  command expr "$@"
}

# 拡張正規表現で呼び出せる
expr "$(id)" : "uid=([0-9]*)\("
echo "-----"

example() {
  ere="$2"; ere2bre bre "$ere"
  echo "=== $ere : $bre ==="
  printf '%s\n' "$1" | grep --color -E "$ere"
  printf '%s\n' "$1" | grep --color "$bre"
}

example 'a\b' 'a\\b'
example 'a(b' 'a\(b'
example 'ab' 'a(b)'
example 'a{b}' 'a\{b\}'
example 'ab' 'a.*'
example 'ac' 'ab?c'
example 'abc' 'ab?c'
example 'a' '(a|b)'
example 'aca' '(a|b)c\1'
example 'az' 'a\z'
4
3
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
4
3