Regex Phone Number Using Validation V2 Golang Package Not Working - regex

I am having some trouble when using github.com/go-validator/validator to validate regex some phone numbers with this prefix +62, 62, 0, for instance number e.g. +628112blabla, 0822blablabla, 628796blablabla.
I have try my regex on online regex tester and no issue with the regex on that. Here the regex is :
(0|\+62|062|62)[0-9]+$
But when I try with my go implement with it, the regex not working. This is my code for implement the purpose :
type ParamRequest struct {
PhoneNumber string `validate:"nonzero,regexp=(0|\+62|062|62)[0-9]+$"`
ItemCode string `validate:"nonzero"`
CallbackUrl string `validate:"nonzero"`
}
func (c *TopupAlloperatorApiController) Post() {
var v models.TopupAlloperatorApi
interf := make(map[string]interface{})
json.Unmarshal(c.Ctx.Input.RequestBody, &interf)
logs.Debug(" Json Input Request ", interf)
var phone, item, callback string
if _, a := interf["PhoneNumber"].(string); a {
phone = interf["PhoneNumber"].(string)
}
if _, b := interf["ItemCode"].(string); b {
item = interf["ItemCode"].(string)
}
if _, c := interf["CallbackUrl"].(string); c {
callback = interf["CallbackUrl"].(string)
}
ve := ParamRequest{
PhoneNumber: phone,
ItemCode: item,
CallbackUrl: callback,
}
logs.Debug(" Param Request ", ve)
err := validator.Validate(ve)
if err == nil {
//success
}else{
// not success
}
Many thanks for anything help. Thank you.

Because you are using regexp to check PhoneNumber that won't be matching if the value is empty it is better to remove nonzero from the validation.
I have checked out documentation and haven't found examples where you can use both: nonzero and regexp.
Also you need to make your regex symbol-escaped, otherwise it won't be detected by reflection. It means you should use (0|\\+62|062|62)[0-9]+$ in your code. Here is example where problem is: symbol escaping in struct tags
And also, please try to use this regexp: ^\\+{0,1}0{0,1}62[0-9]+$

Related

How to check if a string contain 2 same char in a row?

I have a regex like this
REGEX_2_SAME_CHARACTER_IN_A_ROW = "^(?:(.)(?!\\1\\1))*$"
and check password with that regex if it contain 2 same character in a row
contain2SameCharacterInARow, err := regexp.MatchString(REGEX_2_SAME_CHARACTER_IN_A_ROW, password)
but I get this error
error match regex 2 same char in a row: error parsing regexp: invalid or unsupported Perl syntax: `(?!`
I have read other question that using regexp.MustCompile but I don't know how to handle or code it, is there anyone can help me with the solution?
Here you can check my full code for validate password
https://play.golang.com/p/5Fj4-UPvL8s
You don't need the anchor, the non-capturing group, nor the negative lookahead. Simply match and capture any character ((.)) followed by itself (\\1).
REGEX_2_SAME_CHARACTER_IN_A_ROW = "(.)\\1"
But this brings us to the next problem: Go regexes do not support back references, so you need to find a different solution. One would be looping the string yourself.
Here's a solution with a simple loop:
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
fmt.Println(ValidatePassword("passsword01"))
}
func ContainsRepeatedChar(s string) bool {
chars := strings.Split(s, "")
char := chars[0]
for i := 1; i < len(chars); i++ {
if (chars[i] == char) {
return true
}
char = chars[i]
}
return false
}
func ValidatePassword(password string) error {
contain2SameCharacterInARow := ContainsRepeatedChar(password)
if contain2SameCharacterInARow {
fmt.Println("duplicated char")
return errors.New("invalid password")
}
fmt.Println("all good")
return nil
}

Convenient way to get the first char index of a given string that caused a specific text pattern not to match in Rust?

Language:
Rust
Rust regex crate: https://docs.rs/regex/1.5.4/regex/
Use case:
Printing friendly diagnostic message to user that inputs text that does not match an expected regex pattern
e.g.
if patterns are Regex::new(r"^--(\w+)=(\w+)$").unwrap(); and Regex = Regex::new(r"^-(\w+)$").unwrap();
and user inputs "---abc"
user can see diagnostic like:
"---abc"
^ Problem with character "-" at index 2.
Expecting format "--key=value".
^ Does not match expected format at index 2.
Possible solution:
Can I do something with capture groups? (They might only be relevant if there is a match). If no solution with capture groups, what else?
// "-a[bc..]" or "--key=value"
lazy_static! {
static ref SHORT_OPTION_RE: Regex = Regex::new(r"^-(\w+)$").unwrap();
static ref LONG_OPTION_RE: Regex = Regex::new(r"^--(\w+)=(\w+)$").unwrap();
}
// long option example
let caps = LONG_OPTION_RE.captures(s).ok_or(e_msg)?;
let key = caps.get(1).unwrap().as_str().to_string();
let value = caps.get(2).unwrap().as_str().to_string();
if key.is_some { }
Issue:
Can't get exact char index that caused capture group not to match.
Alternatives:
Just manually add in if/else checks for various indexes to try to catch every error scenario ("---a", "-a=b", etc) (Essentially implement mini parser that generates diagnostic message and problematic char index without using regex)
Out of scope:
I do not need recommendations for cli program libs/frameworks (unless you're pointing to an implementation detail within one)
Edit:
Modified question to be more generic than just regex.
I would use a parser like nom.
Here is a quick and partial implementation of your use case:
use nom::{
bytes::complete::tag, character::complete::alphanumeric1, combinator::map, sequence::tuple,
IResult,
};
#[derive(Debug)]
struct OptPair {
key: String,
value: String,
}
fn parse_option(input: &str) -> IResult<&str, OptPair> {
map(
tuple((tag("--"), alphanumeric1, tag("="), alphanumeric1)),
|(_, k, _, v): (&str, &str, &str, &str)| OptPair {
key: k.to_owned(),
value: v.to_owned(),
},
)(input)
}
fn test_parse(input: &str) {
println!("TEST: input = \"{}\":", input);
match parse_option(input) {
Ok((_, opt_pair)) => println!(" Ok, {:?}", opt_pair),
Err(err) => match err {
nom::Err::Incomplete(_) => eprintln!(" Incomplete"),
nom::Err::Error(err) => {
let offset = err.input.as_ptr() as usize - input.as_ptr() as usize;
eprintln!(" Error at index {}", offset);
}
nom::Err::Failure(_err) => println!(" Failure"),
},
}
}
fn main() {
test_parse("--foo=bar");
test_parse("---foo=bar");
test_parse("--foo=");
test_parse("Hello");
}
Output:
TEST: input = "--foo=bar":
Ok, OptPair { key: "foo", value: "bar" }
TEST: input = "---foo=bar":
Error at index 2
TEST: input = "--foo=":
Error at index 6
TEST: input = "Hello":
Error at index 0

AmazonCloudWatch PutMetricData request format parsing

How to parse PutMetricData Sample Request as show below.
I want to parse all the MetricData and stores the values in a struct in golang.
https://monitoring.&api-domain;/doc/2010-08-01/
?Action=PutMetricData
&Version=2010-08-01
&Namespace=TestNamespace
&MetricData.member.1.MetricName=buffers
&MetricData.member.1.Unit=Bytes
&MetricData.member.1.Value=231434333
&MetricData.member.1.Dimensions.member.1.Name=InstanceID
&MetricData.member.1.Dimensions.member.1.Value=i-aaba32d4
&MetricData.member.1.Dimensions.member.2.Name=InstanceType
&MetricData.member.1.Dimensions.member.2.Value=m1.small
&MetricData.member.2.MetricName=latency
&MetricData.member.2.Unit=Milliseconds
&MetricData.member.2.Value=23
&MetricData.member.2.Dimensions.member.1.Name=InstanceID
&MetricData.member.2.Dimensions.member.1.Value=i-aaba32d4
&MetricData.member.2.Dimensions.member.2.Name=InstanceType
&MetricData.member.2.Dimensions.member.2.Value=m1.small**
&AUTHPARAMS
Not able to understand this is in which format and how to parse it. Any library available to generate and parse this kind of formatted message?
If you remove the newlines that is a URL. Start with url.Parse, then use the Query() function to get access to the url parameters:
func main() {
var input = `https://monitoring.&api-domain;/doc/2010-08-01/
?Action=PutMetricData
&Version=2010-08-01
&Namespace=TestNamespace
&MetricData.member.1.MetricName=buffers
&MetricData.member.1.Unit=Bytes
&MetricData.member.1.Value=231434333
&MetricData.member.1.Dimensions.member.1.Name=InstanceID
&MetricData.member.1.Dimensions.member.1.Value=i-aaba32d4
&MetricData.member.1.Dimensions.member.2.Name=InstanceType
&MetricData.member.1.Dimensions.member.2.Value=m1.small
&MetricData.member.2.MetricName=latency
&MetricData.member.2.Unit=Milliseconds
&MetricData.member.2.Value=23
&MetricData.member.2.Dimensions.member.1.Name=InstanceID
&MetricData.member.2.Dimensions.member.1.Value=i-aaba32d4
&MetricData.member.2.Dimensions.member.2.Name=InstanceType
&MetricData.member.2.Dimensions.member.2.Value=m1.small**
&AUTHPARAMS`
// possibly also needs to replace \r
input = strings.ReplaceAll(input, "\n", "")
uri, err := url.Parse(input)
if err != nil {
log.Fatal(err)
}
for key, val := range uri.Query() {
fmt.Println(key, val)
}
}
Playground
From here on out it's up to you how you want the target struct to look like.

phrase search in meteor search-source package

I have a meteor app for which I added the search-source package to search certain collections and it works partially. That is, when I search for the term foo bar it returns results for each of "foo" and "bar". This is fine, but I want to also be able to wrap the terms in quotes this way: "foo bar" and get results for an exact match only. at the moment when i do this i get an empty set. Here is my server code:
//Server.js
SearchSource.defineSource('FruitBasket', function(searchText, options) {
// options = options || {}; // to be sure that options is at least an empty object
if(searchText) {
var regExp = buildRegExp(searchText);
var selector = {$or: [
{'fruit.name': regExp},
{'fruit.season': regExp},
{'fruit.treeType': regExp}
]};
return Basket.find(selector, options).fetch();
} else {
return Basket.find({}, options).fetch();
}
});
function buildRegExp(searchText) {
// this is a dumb implementation
var parts = searchText.trim().split(/[ \-\:]+/);
return new RegExp("(" + parts.join('|') + ")", "ig");
}
and my client code:
//Client.js
Template.dispResults.helpers({
getPackages_fruit: function() {
return PackageSearch_fruit.getData({
transform: function(matchText, regExp) {
return matchText.replace(regExp, "<b>$&</b>")
},
sort: {isoScore: -1}
});
}
});
Thanks in advance!
I've modified the .split pattern so that it ignores everything between double quotes.
/[ \-\:]+(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/
Thus, you can simply wrap an exact phrase search in double quotes and it won't get split.
There is one more thing; since we don't need the quotes, they are removed in the next line using a .map function with a regex that replaces double quotes at the start or the end of a string part: /^"|"$/
Sample code:
function buildRegExp(searchText) {
// exact phrase search in double quotes won't get split
var arr = searchText.trim().split(/[ \-\:]+(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/);
var parts = arr.map(function(x){return x.replace(/^"|"$/g, '');});
return new RegExp("(" + parts.join('|') + ")", "ig");
}
console.log(buildRegExp("foo bar"));
console.log(buildRegExp("\"foo bar\""));

Golang Regular Expressions - what am I doing incorrectly?

As a personal project, trying to learn Go(lang) by applying it to something, I am writing an EMCAScript/JavaScript "compiler"; all it will (initially) do is allow you to include other .js files.
Functionality aside, I am pulling my hair out trying to figure out the regexp package. Here is the snippet that does not seem to be doing what I want it to:
// Note: "lines" is an array of strings.
var includeRegex, _ = regexp.Compile("^[ \t]*include[(]{1}\"([^\"]+)\"[)]{1};")
for _, line := range lines {
var isInclude = includeRegex.Match([]byte(line))
if isInclude {
var includeFile = includeRegex.FindString(line)
fmt.Println("INCLUDE", includeFile)
} else {
// ...
}
I have already stumbled across Go's subset of regular expressions, hence why the regex does not read as ^\s*include\("([^"]+)"\);. I have already tested both the preferred, and the Go-style regex, in RegexPal, and both definitely work. The match just never seems to occurr; what am I doing wrong?
For what it's worth, the include() statement I am trying to parse looks like so:
include("somefile.js");
EDIT: For what it's worth, I am keeping the code here.
This seems to work with the latest weekly
package main
import (
"fmt"
"log"
"regexp"
"strings"
)
func main() {
includeRegex, err := regexp.Compile(`^\s*include\("(\\\"|[^"])+"\);`)
if err != nil {
log.Fatal(err)
}
for _, line := range strings.Split(`
foo
include "abc.def"
include("file.js");
include "me\"to\""
include("please\"!\"");
nothing here
`, "\n") {
if includeRegex.Match([]byte(line)) {
includeFile := includeRegex.FindString(line)
fmt.Println("INCLUDE", includeFile)
} else {
fmt.Printf("no match for \"%s\"\n", line)
}
}
}
Output:
$ go build && ./tmp
no match for ""
no match for "foo"
no match for "include "abc.def""
INCLUDE include("file.js");
no match for " include "me\"to\"""
INCLUDE include("please\"!\"");
no match for " nothing here "
no match for ""
$
Try putting the following line at the start of your program:
println(runtime.Version())
It should print weekly.2012-03-13 or something close to that date.