正则表达式匹配对我来说有些奇怪。

huangapple go评论96阅读模式
英文:

Regex match does weird things for me

问题

我正在尝试创建一个简单的命令行日期输入函数。

在使用golang的正则表达式模式匹配时,我遇到了奇怪的行为:正确的模式匹配返回false,但会干扰我的循环,而不正确的模式只返回false。以下是产生错误的函数:

func ReadDate(fieldname string) (value string) {
    var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
    for {
        value = ""
        fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
        fmt.Scanf("%s\n", &value)
        if value == "" {
            break // empty value is ok for input
        }
        fmt.Printf("validid %v\n", validID.MatchString(value))
        if validID.MatchString(value) {
            break
        } else {
            fmt.Printf("invalid entry, try again..\n")
        }
    }
    return
}

当我运行它时,我得到以下结果:

date - e.g. 2014 Jan 01: x
validid false
date - e.g. 2014 Jan 01: x
validid false
date - e.g. 2014 Jan 01: 2014 Jan 01
validid false
date - e.g. 2014 Jan 01: validid false
date - e.g. 2014 Jan 01: validid false
date - e.g. 2014 Jan 01: 

请注意,最后一个符合正确模式的输入会再次通过无限循环运行两次,然后停止。有任何想法为什么会发生这种情况吗?

Go版本为1.2,Linux/386。

英文:

I'm trying to create a simple command line date entry function.

I get a weird behavior when using regexp pattern matching with golang: correct pattern mach returns false but messes with my loop while incorrect pattern just returns false. Here is the function that produces the error:

func ReadDate(fieldname string) (value string) {
	var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
	for {
		value = ""
		fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
		fmt.Scanf("%s\n", &value)
		if value == "" {
			break // empty value is ok for input
		}
		fmt.Printf("validid %v\n", validID.MatchString(value))
		if validID.MatchString(value) {
			break
		} else {
			fmt.Printf("invalid entry, try again..\n")
		}
	}
	return
}

when I run it, I get the following:

date - e.g. 2014 Jan 01: x
validid false
date - e.g. 2014 Jan 01: x
validid false
date - e.g. 2014 Jan 01: 2014 Jan 01
validid false
date - e.g. 2014 Jan 01: validid false
date - e.g. 2014 Jan 01: validid false
date - e.g. 2014 Jan 01: 

Notice how the last entry with the correct pattern runs another two times through the infinite loop and then stops. Any ideas why this might happen?

Go version 1.2 Linux/386

答案1

得分: 4

问题是Scanf在整行读取之前就返回了。我已经修改了你的代码,使用了bufio.Scanneros.Stdin,现在它可以正常工作了:

package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
)

func ReadDate(fieldname string) (value string) {
	var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
	fmt.Printf("%s - 例如 2014 Jan 01: ", fieldname)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		value = scanner.Text()
		fmt.Printf("读取的值: '%s'\n", value)
		if value == "" {
			break // 空值对输入来说是可以的
		}
		fmt.Printf("validid %v\n", validID.MatchString(value))
		if validID.MatchString(value) {
			break
		} else {
			fmt.Printf("无效的输入,请重试..\n")
		}
		fmt.Printf("%s - 例如 2014 Jan 01: ", fieldname)

	}
	return
}

func main() {
	fmt.Println("返回值: ", ReadDate("foo"))
}
英文:

the problem is Scanf returns before the whole line is read. I've modified your code to use bufio.Scanner and os.Stdin, and it works now:

package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
)

func ReadDate(fieldname string) (value string) {
	var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
	fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		value = scanner.Text()
		fmt.Printf("Read value: '%s'\n", value)
		if value == "" {
			break // empty value is ok for input
		}
		fmt.Printf("validid %v\n", validID.MatchString(value))
		if validID.MatchString(value) {
			break
		} else {
			fmt.Printf("invalid entry, try again..\n")
		}
		fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)

	}
	return
}

func main() {
	fmt.Println("Returned ", ReadDate("foo"))
}

huangapple
  • 本文由 发表于 2014年2月17日 20:47:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/21829546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定