从正则表达式获取文本字段输入范围

时间:2022-10-27 09:50:08

When a textbox receives focus I want to show an on-screen keyboard. There are several keyboards that I can show based on the input scope of the field. The problem is that the textbox's expected user input is server-driven and I am not provided with an input scope property (nor can I add one). In fact, all I have is the regex to validate the user's input for the field.

当文本框获得焦点时,我想要显示屏幕键盘。我可以根据字段的输入范围显示几个键盘。问题是文本框的预期用户输入是服务器驱动的,我没有提供输入范围属性(也不能添加一个)。事实上,我所拥有的只是用于验证用户输入字段的正则表达式。

Based on any regex string, what is the best way to determine an input scope for a textbox?

基于任何正则表达式字符串,确定文本框输入范围的最佳方法是什么?

Input scopes are: Name (letters keyboard only), PhoneNumber (numbers only keyboard), etc.

输入范围是:名称(仅限字母键盘),PhoneNumber(仅限数字键盘)等。

Typical regex: "^[0-9]{4,4}$", "^[0-9]{10,10}$" but may be much more complex.

典型的正则表达式:“^ [0-9] {4,4} $”,“^ [0-9] {10,10} $”但可能要复杂得多。

2 个解决方案

#1


3  

Hard coding a map of regex's to input types seems like an option, but a poor one.

将正则表达式的地图硬编码为输入类型似乎是一种选择,但是很差。

Do you know how many classes of inputs there are? I'll assume you do. You need to create a sample set of inputs which match various input classes, and then make a truth table to compare it to, like

你知道有多少类输入吗?我假设你这样做。您需要创建一个匹配各种输入类的输入样本集,然后创建一个真值表来比较它,比如

EXAMPLE      | PHONE | NAME | TEXT |   
2061234567   | T     | F    | T    |
206.123.4567 | T     | F    | T    |
hello        | F     | T    | T    |
brian        | F     | T    | T    |
bADSFj@$$    | F     | F    | T    |

Take the regex for the field, run the example strings through the regex, and compare the match vs. not match to a table that maps truth values to input classes. Here's an example solution, though you may want to use some heuristic instead of doing exact matches. (Java):

获取字段的正则表达式,通过正则表达式运行示例字符串,并将匹配与不匹配比较为将真值映射到输入类的表。这是一个示例解决方案,但您可能希望使用一些启发式而不是完全匹配。 (JAVA):

int PHONE_CLASS = 0x18; // 11000 - the truth table value from above
...
Map<int, Keyboard> keyboardMap;
keyboardMap.put(PHONE_CLASS, phoneKeyboard);
...
Keyboard inferKeyboard(Pattern regex) {
  int matches = 0;
  for (String example : examples) {
    matches = matches << 1;
    if (regex.matches(example)) { matches++; }
  }
  if (!keyboardMap.containsKey(matches)) { return GENERIC_KEYBOARD; }
  return keyboardMap.get(matches);
}

#2


0  

The trick is to specify the formats for each input scope within an if conditional in a regex pattern. I start out with a phone number because it appears to be the most limiting; numbers, dash, period slash). Then I work my way to others. Note the regex phone pattern is not super robust so you may need to tweak it.. Once found check the regex pattern to see what text is put into the named match capture group. If the named match capture group has text, viola! one has identified what it is.

诀窍是在正则表达式模式中的if条件中指定每个输入范围的格式。我从一个电话号码开始,因为它似乎是最有限的;数字,短划线,句号斜线)。然后我向别人努力。请注意,正则表达式手机模式不是非常强大,因此您可能需要对其进行调整。一旦找到,请检查正则表达式模式以查看将哪些文本放入指定的匹配捕获组。如果指定的匹配捕获组有文本,中提琴!一个人已经确定了它是什么。

This example has three types, Phone, Address (address is numbers then a space then text) followed by the default of text. But you can add more ifs internally. The pattern is commented for easier use.

此示例有三种类型,电话,地址(地址是数字,然后是空格,然后是文本),后跟默认的文本。但是你可以在内部添加更多ifs。评论模式以便于使用。

void Main()
{

    Console.WriteLine ("303-867-5309".DetermineScope() == InputScope.Phone); // True
    Console.WriteLine ("1811 South Quebec Way".DetermineScope() == InputScope.Address); // True
    Console.WriteLine ("Turk 181".DetermineScope() == InputScope.Text); // True

}

public enum InputScope
    {
       Phone,           // Digits and dividers
       Address,         // number space then text
         Text,            // Everything is text...final catch all.
    };


public static class TestCaseExtensions
{

    public static InputScope DetermineScope(this string text)
    {

        string pattern = @"
(?(^[\d.\-/\\]+$)           # If: First check for phone; just numbers and dividers (no spaces)
   (?<Phone>[\d.\-/\\]+)    #    Place into Phone named capture group
 |                          # Else: start a new check
   (?(^\d+\s\w+)            # If Check for address (if Address)
     (?<Address>.*)       #    Looks like its an address, place into address capture group
    |                     # Else
     (?<Text>.*)          #   Nope just text, place into text capture group
   )
)";

    var result = InputScope.Text; // Default to the lowest...text

    // Ignore allows us to document pattern; it is not related to processing text.
    var match = Regex.Match(text, pattern, RegexOptions.IgnorePatternWhitespace);

    if (match.Success)
    {
        result = 
        Enum.GetValues(typeof(InputScope))
            .OfType<InputScope>()
            .Where (tp => match.Groups[tp.ToString()].Success)
            .First ();

    }

    return result;

    }

}

I've written more on the subject: Regular Expressions and the If Conditional.

我已经写了更多关于这个主题:正则表达式和If条件。

#1


3  

Hard coding a map of regex's to input types seems like an option, but a poor one.

将正则表达式的地图硬编码为输入类型似乎是一种选择,但是很差。

Do you know how many classes of inputs there are? I'll assume you do. You need to create a sample set of inputs which match various input classes, and then make a truth table to compare it to, like

你知道有多少类输入吗?我假设你这样做。您需要创建一个匹配各种输入类的输入样本集,然后创建一个真值表来比较它,比如

EXAMPLE      | PHONE | NAME | TEXT |   
2061234567   | T     | F    | T    |
206.123.4567 | T     | F    | T    |
hello        | F     | T    | T    |
brian        | F     | T    | T    |
bADSFj@$$    | F     | F    | T    |

Take the regex for the field, run the example strings through the regex, and compare the match vs. not match to a table that maps truth values to input classes. Here's an example solution, though you may want to use some heuristic instead of doing exact matches. (Java):

获取字段的正则表达式,通过正则表达式运行示例字符串,并将匹配与不匹配比较为将真值映射到输入类的表。这是一个示例解决方案,但您可能希望使用一些启发式而不是完全匹配。 (JAVA):

int PHONE_CLASS = 0x18; // 11000 - the truth table value from above
...
Map<int, Keyboard> keyboardMap;
keyboardMap.put(PHONE_CLASS, phoneKeyboard);
...
Keyboard inferKeyboard(Pattern regex) {
  int matches = 0;
  for (String example : examples) {
    matches = matches << 1;
    if (regex.matches(example)) { matches++; }
  }
  if (!keyboardMap.containsKey(matches)) { return GENERIC_KEYBOARD; }
  return keyboardMap.get(matches);
}

#2


0  

The trick is to specify the formats for each input scope within an if conditional in a regex pattern. I start out with a phone number because it appears to be the most limiting; numbers, dash, period slash). Then I work my way to others. Note the regex phone pattern is not super robust so you may need to tweak it.. Once found check the regex pattern to see what text is put into the named match capture group. If the named match capture group has text, viola! one has identified what it is.

诀窍是在正则表达式模式中的if条件中指定每个输入范围的格式。我从一个电话号码开始,因为它似乎是最有限的;数字,短划线,句号斜线)。然后我向别人努力。请注意,正则表达式手机模式不是非常强大,因此您可能需要对其进行调整。一旦找到,请检查正则表达式模式以查看将哪些文本放入指定的匹配捕获组。如果指定的匹配捕获组有文本,中提琴!一个人已经确定了它是什么。

This example has three types, Phone, Address (address is numbers then a space then text) followed by the default of text. But you can add more ifs internally. The pattern is commented for easier use.

此示例有三种类型,电话,地址(地址是数字,然后是空格,然后是文本),后跟默认的文本。但是你可以在内部添加更多ifs。评论模式以便于使用。

void Main()
{

    Console.WriteLine ("303-867-5309".DetermineScope() == InputScope.Phone); // True
    Console.WriteLine ("1811 South Quebec Way".DetermineScope() == InputScope.Address); // True
    Console.WriteLine ("Turk 181".DetermineScope() == InputScope.Text); // True

}

public enum InputScope
    {
       Phone,           // Digits and dividers
       Address,         // number space then text
         Text,            // Everything is text...final catch all.
    };


public static class TestCaseExtensions
{

    public static InputScope DetermineScope(this string text)
    {

        string pattern = @"
(?(^[\d.\-/\\]+$)           # If: First check for phone; just numbers and dividers (no spaces)
   (?<Phone>[\d.\-/\\]+)    #    Place into Phone named capture group
 |                          # Else: start a new check
   (?(^\d+\s\w+)            # If Check for address (if Address)
     (?<Address>.*)       #    Looks like its an address, place into address capture group
    |                     # Else
     (?<Text>.*)          #   Nope just text, place into text capture group
   )
)";

    var result = InputScope.Text; // Default to the lowest...text

    // Ignore allows us to document pattern; it is not related to processing text.
    var match = Regex.Match(text, pattern, RegexOptions.IgnorePatternWhitespace);

    if (match.Success)
    {
        result = 
        Enum.GetValues(typeof(InputScope))
            .OfType<InputScope>()
            .Where (tp => match.Groups[tp.ToString()].Success)
            .First ();

    }

    return result;

    }

}

I've written more on the subject: Regular Expressions and the If Conditional.

我已经写了更多关于这个主题:正则表达式和If条件。