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

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

Regex match does weird things for me

问题

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

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

  1. func ReadDate(fieldname string) (value string) {
  2. var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
  3. for {
  4. value = ""
  5. fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
  6. fmt.Scanf("%s\n", &value)
  7. if value == "" {
  8. break // empty value is ok for input
  9. }
  10. fmt.Printf("validid %v\n", validID.MatchString(value))
  11. if validID.MatchString(value) {
  12. break
  13. } else {
  14. fmt.Printf("invalid entry, try again..\n")
  15. }
  16. }
  17. return
  18. }

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

  1. date - e.g. 2014 Jan 01: x
  2. validid false
  3. date - e.g. 2014 Jan 01: x
  4. validid false
  5. date - e.g. 2014 Jan 01: 2014 Jan 01
  6. validid false
  7. date - e.g. 2014 Jan 01: validid false
  8. date - e.g. 2014 Jan 01: validid false
  9. 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:

  1. func ReadDate(fieldname string) (value string) {
  2. var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
  3. for {
  4. value = ""
  5. fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
  6. fmt.Scanf("%s\n", &value)
  7. if value == "" {
  8. break // empty value is ok for input
  9. }
  10. fmt.Printf("validid %v\n", validID.MatchString(value))
  11. if validID.MatchString(value) {
  12. break
  13. } else {
  14. fmt.Printf("invalid entry, try again..\n")
  15. }
  16. }
  17. return
  18. }

when I run it, I get the following:

  1. date - e.g. 2014 Jan 01: x
  2. validid false
  3. date - e.g. 2014 Jan 01: x
  4. validid false
  5. date - e.g. 2014 Jan 01: 2014 Jan 01
  6. validid false
  7. date - e.g. 2014 Jan 01: validid false
  8. date - e.g. 2014 Jan 01: validid false
  9. 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,现在它可以正常工作了:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "regexp"
  7. )
  8. func ReadDate(fieldname string) (value string) {
  9. var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
  10. fmt.Printf("%s - 例如 2014 Jan 01: ", fieldname)
  11. scanner := bufio.NewScanner(os.Stdin)
  12. for scanner.Scan() {
  13. value = scanner.Text()
  14. fmt.Printf("读取的值: '%s'\n", value)
  15. if value == "" {
  16. break // 空值对输入来说是可以的
  17. }
  18. fmt.Printf("validid %v\n", validID.MatchString(value))
  19. if validID.MatchString(value) {
  20. break
  21. } else {
  22. fmt.Printf("无效的输入,请重试..\n")
  23. }
  24. fmt.Printf("%s - 例如 2014 Jan 01: ", fieldname)
  25. }
  26. return
  27. }
  28. func main() {
  29. fmt.Println("返回值: ", ReadDate("foo"))
  30. }
英文:

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:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "regexp"
  7. )
  8. func ReadDate(fieldname string) (value string) {
  9. var validID = regexp.MustCompile(`^\d\d\d\d\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dez)\s\d\d$`)
  10. fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
  11. scanner := bufio.NewScanner(os.Stdin)
  12. for scanner.Scan() {
  13. value = scanner.Text()
  14. fmt.Printf("Read value: '%s'\n", value)
  15. if value == "" {
  16. break // empty value is ok for input
  17. }
  18. fmt.Printf("validid %v\n", validID.MatchString(value))
  19. if validID.MatchString(value) {
  20. break
  21. } else {
  22. fmt.Printf("invalid entry, try again..\n")
  23. }
  24. fmt.Printf("%s - e.g. 2014 Jan 01: ", fieldname)
  25. }
  26. return
  27. }
  28. func main() {
  29. fmt.Println("Returned ", ReadDate("foo"))
  30. }

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:

确定