r remove words which begins and ends with dashes - r

How to remove words with dashes (as prefixes or suffixes) from such string:
x <- "word -o -dod -3 -33 dp-pd -d- --- 140 -- s- S- SS- s3- 3e- 33- 3- s SS avf-ada"
And obtain:
word dp-pd 140 s SS avf-ada
Occasionally, standalone dashes also can be removed.
I've found a solution thanks to regex101: (\s-\S+)|(\S+-\s)

I suggest using
x <- "word -o -dod -3 -33 dp-pd -d- --- 140 -- s- S- SS- s3- 3e- 33- 3- s SS avf-ada -"
trimws(gsub("(?:\\S+-\\B|\\B-\\S+|\\B-\\B)\\s*", "", x, perl=TRUE))
See the regex demo and an R demo.
Details:
(?:\S+-\B|\B-\S+|\B-\B) - either of the two alternatives:
\S+-\B - 1+ chars other than whitespace, - and a non-word boundary, that is, the - must be either at the end of string or before a non-word char
| - or
\B-\S+ - a non-word boundary, that is, the - should only be matched if preceded with a non-word char or start of string, then a hyphen and 1+ chars other than whitespace
\B-\B - any - enclosed with non-word boundaries (at the end/start of string or between non-word chars)
\s* - 0+ whitespaces.
The perl=TRUE needs to be used because of the non-word boundary that does not work correctly with a TRE regex version.

Related

grep in R, literal and pattern match

I have seen in manuals how to use grep to match either a pattern or an exact string. However, I cannot figure out how to do both at the same time. I have a latex file where I want to find the following pattern:
\caption[SOME WORDS]
and replace it with:
\caption[\textit{SOME WORDS}]
I have tried with:
texfile <- sub('\\caption[','\\caption[\\textit ', texfile, fixed=TRUE)
but I do not know how to tell grep that there should be some text after the square bracket, and then a closed square bracket.
You can use
texfile <- "\\caption[SOME WORDS]" ## -> \caption[\textit{SOME WORDS}]
texfile <-gsub('(\\\\caption\\[)([^][]*)]','\\1\\\\textit{\\2}]', texfile)
cat(texfile)
## -> \caption[\textit{SOME WORDS}]
See the R demo online.
Details:
(\\caption\[) - Group 1 (\1 in the replacement pattern): a \caption[ string
([^][]*) - Group 2 (\2 in the replacement pattern): any zero or more chars other than [ and ]
] - a ] char.
Another solution based on a PCRE regex:
gsub('\\Q\\caption[\\E\\K([^][]*)]','\\\\textit{\\1}]', texfile, perl=TRUE)
See this R demo online. Details:
\Q - start "quoting", i.e. treating the patterns to the right as literal text
\caption[ - a literal fixed string
\E - stop quoting the pattern
\K - omit text matched so far
([^][]*) - Group 1 (\1): any zero or more non-bracket chars
] - a ] char.

Regex to match a pattern but not two specific cases

I want to match every cases of "-", but not these ones:
[\d]-[A-Z]
[A-Z]-[\d]
I tried this pattern: ((?<![A-Z])-(?![0-9]))|((?<![0-9])-(?![A-Z])) but some results are incorrect like: "RUA VF-32 N"
Can anyone help me?
A simple approach is to use grep with your current logic and inverting the result, and then run another grep to only keep those items that have a hyphen in them:
x <- c("QUADRA 120 - ASA BRANCA","FAZENDA LAGE -RODOVIA RIO VERDE","C-15","99-B","A-A")
grep("-", grep("[A-Z]-\\d|\\d-[A-Z]", x, invert=TRUE, value=TRUE), value=TRUE, fixed=TRUE)
# => [1] "QUADRA 120 - ASA BRANCA" "FAZENDA LAGE -RODOVIA RIO VERDE"
# [3] "A-A"
Here, [A-Z]-\\d|\\d-[A-Z] matches a hyphen either in between an uppercase ASCII etter or a digit or betweena digit and an ASCII uppercase letter. If there is a match, the result is inverted due to invert=TRUE.
See the R demo.
To only match - in all contexts other than in between a letter and a digit, you may use the PCRE regex based on SKIP-FAIL technique like
> grep("(?:\\d-[A-Z]|[A-Z]-\\d)(*SKIP)(*F)|-", x, perl=TRUE)
[1] 1 2
See this regex demo
Details
(?:\d-[A-Z]|[A-Z]-\d) - a non-capturing group that matches either a digit, - and then uppercase ASCII letter, or an uppercase ASCII letter, - and a digit
(*SKIP)(*F) - omit the current match and proceed looking for the next match at the end of the "failed" match
| - or
- - a hyphen.

RegularExpressionValidator for word count that handles punctuation

I thought I had a great regex for limiting the number of words entered into a TextBox, however I discovered, it fails when there is punctuation in the text.
How can I modify this regex (or use a different one) that correctly counts words that may be made up of several sentences or contain other symbols?
^(?:\b\w+\b[\s\r\n]*){1,10}$
This limits the words to 10.
I think this is the ONLY WAY it can be done.
I would like to see a better way if it exists.
(requires an atomic group)
For Unicode:
^\s*(?>[^\pL\pN]*[\pL\pN](?:[\pL\pN_-]|\pP(?=[\pL\pN\pP_-])|[?.!])*\s*){1,10}$
Explained
^
\s*
(?>
[^\pL\pN]* [\pL\pN] # Not letters/numbers, followed by letter/number
(?:
[\pL\pN_-] # Letter/number or '-'
|
\pP # Or, punctuation if followed by punctuation/letter/number or '-'
(?= [\pL\pN\pP_-] )
|
[?.!] # Or, (Add) Special word ending punctuation
)*
\s*
){1,10}
$
For Ascii:
^\s*(?>[\W_]*[^\W_](?:\w|[[:punct:]_-](?=[\w[:punct:]-])|[?.!])*\s*){1,10}$
Expanded
^
\s*
(?>
[\W_]* [^\W_]
(?:
\w
|
[[:punct:]_-]
(?= [\w[:punct:]-] )
|
[?.!]
)*
\s*
){1,10}
$

extract string from in R using regex

I have this vector:
jvm<-c("test - PROD_DB_APP_185b#SERVER01" ,"uat - PROD_DB_APP_SYS[1]#SERVER2")
I need to extract text until "[" or if there is no "[", then until the "#" character.
result should be
PROD_DB_APP_185b
PROD_DB_APP_SYS
I've tried something like this:
str_match(jvm, ".*\\-([^\\.]*)([.*)|(#.*)")
not working, any ides?
A sub solution with base R:
jvm<-c("test - PROD_DB_APP_185b#SERVER01" ,"uat - PROD_DB_APP_SYS[1]#SERVER2")
sub("^.*?\\s+-\\s+([^#[]+).*", "\\1", jvm)
See the online R demo
Details:
^ - start of string
.*? - any 0+ chars as few as possible
\\s+-\\s+ - a hyphen enclosed with 1 or more whitespaces
([^#[]+) - capturing group 1 matching any 1 or more chars other than #
and [
.* - any 0+ chars, up to the end of string.
Or a stringr solution with str_extract:
str_extract(jvm, "(?<=-\\s)[^#\\[]+")
See the regex demo
Details:
(?<=-\\s) - a positive lookbehind that matches an empty string that is preceded with a - and a whitespace immediately to the left of the current location
[^#\\[]+ - 1 or more chars other than # and [.

Why does is this end of line (\\b) not recognised as word boundary in stringr/ICU and Perl

Using stringr i tried to detect a € sign at the end of a string as follows:
str_detect("my text €", "€\\b") # FALSE
Why is this not working? It is working in the following cases:
str_detect("my text a", "a\\b") # TRUE - letter instead of €
grepl("€\\b", "2009in €") # TRUE - base R solution
But it also fails in perl mode:
grepl("€\\b", "2009in €", perl=TRUE) # FALSE
So what is wrong about the €\\b-regex? The regex €$ is working in all cases...
When you use base R regex functions without perl=TRUE, TRE regex flavor is used.
It appears that TRE word boundary:
When used after a non-word character matches the end of string position, and
When used before a non-word character matches the start of string position.
See the R tests:
> gsub("\\b\\)", "HERE", ") 2009in )")
[1] "HERE 2009in )"
> gsub("\\)\\b", "HERE", ") 2009in )")
[1] ") 2009in HERE"
>
This is not a common behavior of a word boundary in PCRE and ICU regex flavors where a word boundary before a non-word character only matches when the character is preceded with a word char, excluding the start of string position (and when used after a non-word character requires a word character to appear right after the word boundary):
There are three different positions that qualify as word boundaries:
- Before the first character in the string, if the first character is a word character.
- After the last character in the string, if the last character is a word character.
- Between two characters in the string, where one is a word character and the other is not a word character.
\b
is equivalent to
(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))
which is to say it matches
between a word char and a non-word char,
between a word char and the start of the string, and
between a word char and the end of the string.
€ is a symbol, and symbols aren't word characters.
$ uniprops €
U+20AC <€> \N{EURO SIGN}
\pS \p{Sc}
All Any Assigned Common Zyyy Currency_Symbol Sc Currency_Symbols S Gr_Base Grapheme_Base Graph X_POSIX_Graph GrBase Print X_POSIX_Print Symbol Unicode
If your language supports look-behinds and look-aheads, you could use the following to find a boundary between a space and non-space (treating the start and end as a space).
(?:(?<!\S)(?=\S)|(?<=\S)(?!\S))

Resources