英文:
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.Scanner
和os.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"))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论