[ruby-list:50674] Re: [質問] キャプチャ付き正規表現の後方参照

From: Takahiro Yamaguchi <yamataka@...08.itscom.net>
Date: 2018-06-05 12:42:59 UTC
List: ruby-list #50674
市田さん

山口です。
ご教示ありがとうございます。

>> どの様に記述すればいいのですか?
> 
> コマンドの文法、エラーチェックの方法、コマンドの数など、どこまでのことをしたいのかによって
> 実装方法が変わってくるので、答えようが。。

不躾な質問ですみません。

> 特にrubyでは色々な方法でかけるので、あれこれ考えるのも楽しいですよ。:)
> 
> * 1行で完結
> * 空白で区切られ、かつ1の引数には空白を含まない
> * コマンドは数個
> * 引数はせいぜい1個程度で、ほとんど数字
> 
> 程度であれば、
> 
> cmd, *args = str.split
> 
> として cmd を if で判定するでしょうね。

なるほど。
この様な記述を思い浮かびませんでした。
入力されたのを、正規表現でマッチさせたら楽だなと考え、引数の数字も正規表現でキャプチャという思考に至りました。
勉強になります。
いつも、ご教示ありがとうございます。

> そこそこコマンドの数が多いならテーブル(hash)引きするなり、メソッドを定義しておいて send するなど。

それっぽい感じにはしてるんですけど… 
もっと、プロっぽい記述とかになればいいんですが...
method input は、thread にしています。

def input

  @cmd_tbl = [
    { regexp:       '^ *p *$',
      input:        "p",
      explanation:  "pause execution",
      queue:        $qsl,
      cmd:          :pause},
    { regexp:       '^ *q(uit)* *$',
      input:        "q or quit",
      explanation:  "exit",
      queue:        nil,
      cmd:          :quit},
    { regexp:       '^ *prev *$',
      input:        "prev",
      explanation:  "previous content",
      queue:        $qsl,
      cmd:          :prev},
    { regexp:       '^ *n(ext)* *$',
      input:        "n or next",
      explanation:  "next content",
      queue:        $qsl,
      cmd:          :next},
    { regexp:       '^ *l(ist)* *$',
      input:        "l or list",
      explanation:  "list the speech table",
      queue:        $qsl,
      cmd:          :list},
    { regexp:       '^ *r(epeat)* *$',
      input:        "r or repeat",
      explanation:  "toggle repeat execution",
      queue:        $qsl,
      cmd:          :repeat},
    { regexp:       '^ *s(tatus)* *$',
      input:        "s or status",
      explanation:  "info execution thread status",
      queue:        $qsl,
      cmd:          :status},
    { regexp:       '^ *v +(\d+) *$',
      input:        "v no, e.g. v 12",
      explanation:  "speech the 'no' content specified in the speech tbl without target device name",
      queue:        $qsl,
      cmd:          '":direct  #{$1}"'},
    { regexp:       '^ *t +(\d+) *$',
      input:        "t no, e.g. v 12",
      explanation:  "speech the 'no' content specified in the speech tbl with tareget device name",
      queue:        $qsl,
      cmd:          '":tdirect #{$1}"'},

    { regexp:       '^ *sl *$',
      input:        "sl",
      explanation:  "list the single speech table",
      queue:        $qss,
      cmd:          :list},
    { regexp:        '^ *sv +(\d+) *$',
      input:        "sv no e.g sv 10",
      explanation:  "speech 'no' content specified in the single speech tbl without target device name",
      queue:        $qss,
      cmd:          '":direct  #{$1}"'},
    { regexp:       '^ *st +(\d+) *$',
      input:        "st no e.g sv 10",
      explanation:  "speech 'no' content specified in the single speech tbl with target device name",
      queue:        $qss,
      cmd:          '":tdirect #{$1}"'},
    { regexp:       '^ *h(elp)* *$',
      input:        "h or help",
      explanation:  "show the help",
      queue:        nil,
      cmd:          :help},
  ]

  alias quit exit

  def help
    @cmd_tbl.each do |h|
      puts "#{h[:input]}: #{h[:explanation]}"
    end
  end

  loop do 
    cmd = STDIN.gets
    puts "[INFO] input:#{cmd}"

    match = nil
    @cmd_tbl.each do |c|
      if /#{c[:regexp]}/ =~ cmd
        match = true
        x = $1 ? eval(c[:cmd]) : c[:cmd]
        c[:queue] ? c[:queue].push(x) : send(x)
        break
      end
    end

    puts "[WARN] unrecognized cmd:#{cmd}" unless match
  end

end

In This Thread