cleaning phonenumbers using regex - r

I have the following composition of phonenumbers where 33 is the area code:
+331234567
+3301234567
00331234567
003301234567
0331234567
033-123-456-7
0033.1234567
where Im expecting only 331234567
What I have tried to clean those numbers using R
R::tidyverse::str_replace_all(c("+331234567", "033-123-456-7", "0033.1234567"), pattern = "[^0-9.]", replacement = "") removing non-numeric characters
R::tidyverse::str_replace_all("0331234567", pattern = "^0", replacement = "") removing the leading 0
R::tidyverse::str_replace_all("00331234567", pattern = "^00", replacement = "") removing the leading 00
my question is how to remove the zeros in between: 3301234567 or 003301234567 or +3301234567 or 03301234567
Appreciate any help

You can use
gsub("^(?:00?|\\+)330?|\\W", "", x, perl=TRUE)
See the regex demo. See the R demo online.
If there can be more 0s after 33 before the number you need to extract, replace 0? with 0*.
Details
^ - start of string
(?:00?|\+) - 00, 0 or +
330? - 33 or 330
| - or
\W - any non-word char.

You can use ^\+?0*3*0*|[^\s\d]
Pattern explanation:
^ - match beginning of the string
\+? - match + literally, zero or one time.
0* - match zero or more 0
3* - match zero or more 3
| - alternation
[^\s\d] - negated character class - match any character other from whitespace and digit (you could remove \s if you handle one number at a time, it just prevents from matching newline in demo)
Regex demo
It will match unwanted parts separately. First part will clean beginning of a number if it starts with + or 0, second part will clean non-digits inside the number.

Related

Extract substring between two colons / special characters

I want to extract "SUBSTRING" with sub() from the following string:
attribute <- "S4Q7b1_t1_r1: SUBSTRING: some explanation: some explanation - ..."
I used the following code, but unfortunately it didn't work:
sub(".*: (.*) : .*", "\\1", attribute)
Does anyone know an answer for that?
You may use
sub("^[^:]*: ([^:]*).*", "\\1", attribute)
See the regex demo
You need to rely on negated character classes, [^:] that matches any char but :, since .* matches greedily any 0 or more chars. Also, your pattern contains a space before : and it is missing in the string.
Details
^ - start of string
[^:]* - any 0+ chars other than :
: - a colon with a space
-([^:]*) - Capturing group 1 (\1 refers to this value): any 0+ chars other than :
.* - the rest of the string.
R Demo:
attribute <- "S4Q7b1_t1_r1: SUBSTRING: some explanation: some explanation - ..."
sub("^[^:]*: ([^:]*).*", "\\1", attribute)
## => [1] "SUBSTRING"

matching start of a string but not end in R

How can I match all words starting with plan_ and not ending with template without using invert = TRUE? In the below example, I'd like to match only the second string. I tried with negative lookahead but it does not work, maybe because of greediness?
names <- c("plan_x_template", "plan_x")
grep("^plan.*(?!template)$",
names,
value = TRUE, perl = TRUE
)
#> [1] "plan_x_template" "plan_x"
I mean one can also solve the problem with two regex calls but I'd like to see how it works the other way :-)
is_plan <- grepl("^plan_", names)
is_template <- grepl("_template$", names)
names[is_plan & !is_template]
#> [1] "plan_x"
You may use
names <- c("plan_x_template", "plan_x")
grep("^plan(?!.*template)",
names,
value = TRUE, perl = TRUE
)
See the R online demo
The ^plan(?!.*template) pattern matches:
^ - a start of string
plan - a plan substring
(?!.*template) - a negative lookahead that fails the match if, immediately to the left of the current location, there are 0+ chars other than line break chars (since perl = TRUE is used and the pattern is processed with a PCRE engine, the . does not match all possible chars as opposed to the default grep TRE regex engine), as many as possible, followed with template substring.
NOTE: In case of multiline strings, you need to use a DOTALL modifier in the regex, "(?s)^plan(?!.*template)".

Extract digits after matching the certain string second time

I want to extract the digits after second occurance of under score _ from a pattern.
by following the similar posts here
Matching different digits after a lookahead
regex - return all before the second occurrence
I tried
library(stringr)
pattern <- c("1/2/3_500k/855kk_1400k/AVBB")
str_extract(pattern, "(^_){2}(\\d+\\.*\\d*)")
which outputs
[1] NA
instead of 1400. Could you help?
You may use a base R solution with regexpr/regmatches:
regmatches(x, regexpr("^(?:[^_]*_){2}[^_0-9]*\\K\\d*\\.?\\d+", x, perl=TRUE))
Or, with sub:
sub("^(?:[^_]*_){2}[^_0-9]*(\\d*\\.?\\d+).*", "\\1", x)
See the R demo online.
The regex is
^(?:[^_]*_){2}[^_0-9]*\K\d*\.?\d+
See the online regex demo.
Details
^ - start of string
(?:[^_]*_){2} - 2 repetitions of
[^_]* - any 0+ chars other than _
_ - an underscore
[^_0-9]* - any 0+ chars other than _ and digits
\K - match reset operator discarding all text matched so far
\d*\.?\d+ - a float or integer number pattern (0+ digits, an optional . and then 1+ digits).
In the sub regex variation, the \K is not necessary, the number pattern is captured into a capturing group and the rest of string is matched with .* pattern. The result is the contents of Group 1, referred to with the \1 placeholder.
One option could be as:
pattern <- c("1/2/3_500k/855kk_1400k/AVBB")
sub(".*_*_(\\d+).*","\\1", pattern, perl = TRUE)
[1] "1400"
The regex is:
".*_*_(\\d+).*"
Details:
.*_ anything before first _
.*_ anything after first _ and before 2nd _
\\d+ look for digits and take those as selection.
.* anything afterwards.
\\1 replaces matching strings with values found for 1st group.

Replace some text after a string with Regex and Gsub in R

It's a simple question, but I'm not good with Regex. (I tried many expressions without success)
I want to replace all the text (replace for nothing) after a pattern.
My pattern is something like this:
/canais/*/
My data is:
/canais/b3/conheca-o-pai-dos-indices-da-b3/
/canais/cpbs/cvm-abre-audiencia-publica-de-instruc
/canais/stocche-forbes/dividendo-controverso/
The desired result is:
/canais/b3/
/canais/cpbs/
/canais/stocche-forbes/
How can I do it with gsub?
Thanks
You may use the following sub:
x <- c("/canais/b3/conheca-o-pai-dos-indices-da-b3/","/canais/cpbs/cvm-abre-audiencia-publica-de-instruc","/canais/stocche-forbes/dividendo-controverso/")
sub("^(/canais/[^/]+/).*", "\\1", x)
See the online R demo
Details:
^ - start of string
(/canais/[^/]+/) - Group 1 (later referred to with \1) capturing:
/canais/ - a substring /canais/
[^/]+ - 1 or more chars other than /
/ - a slash
.* - any 0+ chars up to the end of string.

Regex - Substitute character in a matching substring

Let's say I have the following string:
input = "askl jmsp wiqp;THIS IS A MATCH; dlkasl das, fm"
I need to replace the white-spaces with underscores, but only in the substrings that match a pattern. (In this case the pattern would be a semi-colon before and after.)
The expected output should be:
output = "askl jmsp wiqp;THIS_IS_A_MATCH; dlkasl das, fm"
Any ideas how to achieve that, preferably using regular expressions, and without splitting the string?
I tried:
gsub("(.*);(.*);(.*)", "\\2", input) # Pattern matching and
gsub(" ", "_", input) # Naive gsub
Couldn't put them both together though.
Regarding the original question:
Substitute character in a matching substring
You may do it easily with gsubfn:
> library(gsubfn)
> input = "askl jmsp wiqp;THIS IS A MATCH; dlkasl das, fm"
> gsubfn(";([^;]+);", function(g1) paste0(";",gsub(" ", "-", g1, fixed=TRUE),";"), input)
[1] "askl jmsp wiqp;THIS-IS-A-MATCH; dlkasl das, fm"
The ;([^;]+); matches any string starting with ; and up to the next ; capturing the text in-between and then replacing the whitespaces with hyphens only inside the captured part.
Another approach is to use a PCRE regex with a \G based regex with gsub:
p = "(?:\\G(?!\\A)|;)(?=[^;]*;)[^;\\s]*\\K\\s"
> gsub(p, "-", input, perl=TRUE)
[1] "askl jmsp wiqp;THIS-IS-A-MATCH; dlkasl das, fm"
See the online regex demo
Pattern details:
(?:\\G(?!\\A)|;) - a custom boundary: either the end of the previous successful match (\\G(?!\\A)) or (|) a semicolon
(?=[^;]*;) - a lookahead check: there must be a ; after 0+ chars other than ;
[^;\\s]* - 0+ chars other than ; and whitespaces
\\K - omitting the text matched so far
\\s - 1 single whitespace character (if multiple whitespaces are to be replaced with 1 hyphen, add + after it).

Resources