string manipulation to remove the name of files - r

I have a list of strings
/temp/123/afedcgid/abc.csv
/temp/123/4388dkfa/abc1.csv
/temp/123/4388dkfa/ab1.csv
I want to remove name of the file from the strings
The results desired are
/temp/123/afedcgid
/temp/123/4388dkfa
/temp/123/4388dkfa
How can i do it. Thanks.

You could try the below,
sub("/[^/]*$", "", x)
It removes all the chars from the last / symbol.
OR
> x <- "/temp/123/afedcgid/abc.csv"
> sub("(.*)/.*", "\\1", x)
[1] "/temp/123/afedcgid"
captures all the chars from the start upto the last / symbol (excluding /). Then the following chars are matched by .*. Replacing the matched chars with chars inside group 1 will give you the desired output.
Example:
> x <- "/temp/123/afedcgid/abc.csv"
> sub("/[^/]*$", "", x)
[1] "/temp/123/afedcgid"
OR
regmatches(x, gregexpr(".+(?=/)", x, perl=TRUE))

Use this regex to catch character you want to replace
\/\w+\.\w+$
try this demo
Demo
files <- c("/temp/123/afedcgid/abc.csv" ,
"/temp/123/4388dkfa/abc1.csv" , "/temp/123/4388dkfa/ab1.csv")
sub("\\/\\w+\\.\\w+$" , "" , files)
as you may know you need to \\ for escaping sequences in R

Related

How to change values before text in string using R

I have multiple strings that are similar to the following pattern:
dat<-("00000000AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0")
I need to change all 0 values to "." before the first character value within a string. My desired output in this example would be:
"........AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0".
I tried using gsub to accomplish this task:
gsub("\\G([^_\\d]*)\\d", ".\\1", dat, perl=T)
Unfortunately it changed all of the 0s to "." instead of the 0s preceding the first "A".
Can someone please help me with this issue?
If you wish to simply replace each leading 0 with a ., you can use
gsub("\\G0", ".", dat, perl=TRUE)
Here, \G0 matches a 0 char at the start of string, and then every time after a successful match. See this regex demo.
If you need to replace each 0 in a string before the first letter you can use
gsub("\\G[^\\p{L}0]*\\K0", ".", dat, perl=TRUE)
Here, \G matches start of string or end of the preceding successful match, [^\p{L}0]* matches zero or more chars other than a letter and 0, then \K omits the matched text, and then 0 matches the 0 char and it is replaced with a .. See this regex demo.
See the R demo online:
dat <- c("00000000AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0","102030405000AZD")
gsub("\\G0", ".", dat, perl=TRUE)
## [1] "........AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0"
## [2] "102030405000AZD"
gsub("\\G[^\\p{L}0]*\\K0", ".", dat, perl=TRUE)
## [1] "........AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0"
## [2] "1.2.3.4.5...AZD"
This is really hard.
So I tried to do it with a custom function:
library(stringr)
dat<-("00000000AAAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0")
Zero_Replacer <- function(x) {
x <- str_split(x, '[A-Za-z]', 2)
x[[1]][1] <- str_replace_all(x[[1]][1], "0", ".")
paste0(x[[1]][1], x[[1]][2])
}
Zero_Replacer(dat)
Output:
[1] "........AAAAAAAAA0AAAAAAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAD0"

Replace multiple consecutive hyphens in R

I have a string which looks like this:
something-------another--thing
I want to replace the multiple dashes with a single one.
So the expected output would be:
something-another-thing
We can try using sub here:
x <- "something-------another--thing"
gsub("-{2,}", "-", x)
[1] "something-another-thing"
More generally, if we want to replace any sequence of two or more of the same character with just the single character, then use this version:
x <- "something-------another--thing"
gsub("(.)\\1+", "\\1", x)
The second pattern could use an explanation:
(.) match AND capture any single letter
\\1+ then match the same letter, at least one or possibly more times
Then, we replace with just the single captured letter.
you can do it with gsub and using regex.
> text='something-------another--thing'
> gsub('-{2,}','-',text)
[1] "something-another-thing"
t2 <- "something-------another--thing"
library(stringr)
str_replace_all(t2, pattern = "-+", replacement = "-")
which gives:
[1] "something-another-thing"
If you're searching for the right regex to search for a string, you can test it out here https://regexr.com/
In the above, you're just searching for a pattern that is a hyphen, so pattern = "-", but we add the plus so that the search is 'greedy' and can include many hyphens, so we get pattern = "-+"

R retrieving strings with sub: Why this does not work?

I would like to extract parts of strings. The string is:
> (x <- 'ab/cd efgh "xyz xyz"')
> [1] "ab/cd efgh \"xyz xyz\""
Now, I would like first to extract the first part:
> # get "ab/cd efgh"
> sub(" \"[/A-Za-z ]+\"","",x)
[1] "ab/cd efgh"
But I don't succeed in extracting the second part:
> # get "xyz xyz"
> sub("(\"[A-Za-z ]+\")$","\\1",x, perl=TRUE)
[1] "ab/cd efgh \"xyz xyz\""
What is wrong with this code?
Thanks for help.
Your last snippet does not work because you reinsert the whole match back into the result: (\"[A-Za-z ]+\")$ matches and captures ", 1+ letters and spaces, " into Group 1 and \1 in the replacement puts it back.
You may actually get the last part inside quotes by removing all chars other than " at the start of the string:
x <- 'ab/cd efgh "xyz xyz"'
sub('^[^"]+', "", x)
See the R demo
The sub here will find and replace just once, and it will match the string start (with ^) followed with 1+ chars other than " with [^"]+ negated character class.
To get this to work with sub, you have to match the whole string. The help file says
For sub and gsub return a character vector of the same length and with the same attributes as x (after possible coercion to character). Elements of character vectors x which are not substituted will be returned unchanged (including any declared encoding).
So to get this to work with your regex, pre-pend the sometimes risky catchall ".*"
sub(".*(\"[A-Za-z ]+\")$","\\1",x, perl=TRUE)
[1] "\"xyz xyz\""

How to delete string or digits after certain pattern?

If there is a vector x that is,
x <- c('/name12/?ad_2','/name13/?ad_3','/name14/?ad_4')
Is there a way to delete the following numbers after 'ad_'?
so the converted x appears as
'/name12/?ad_' '/name13/?ad_' '/name14/?ad_'
I was trying to use gsub function but it didn't work because of the digits followed by 'name'.
You may use a regex with sub (since you perform a single search and replace, you do not need gsub) and use a pattern depending on what you need to include or exclude in the result.
You might use "(\\?ad_)[0-9]+$" to remove ?ad_ + digits and replace with "\\1" to restore the ?ad_ value, or just match the _ and then digits (and replace with _).
See demo code:
> x <- c('/name12/?ad_2','/name13/?ad_3','/name14/?ad_4')
> sub("(\\?ad_)[0-9]+$", "\\1", x)
[1] "/name12/?ad_" "/name13/?ad_" "/name14/?ad_"
> sub("_[0-9]+$", "_", x)
[1] "/name12/?ad_" "/name13/?ad_" "/name14/?ad_"
See the regex demo
Pattern details:
_ - matches an underscore
[0-9]+ - 1 or more (due to the + quantifier matching one or more occurrences, as many as possible)
$ - the end of string.
Since the prefix is the same length for all of them:
x <- c('/name12/?ad_2','/name13/?ad_3','/name14/?ad_4')
substr(x,1,12)
[1] "/name12/?ad_" "/name13/?ad_" "/name14/?ad_"
Otherwise I would grep it.

Extract first X Numbers from Text Field using Regex

I have strings that looks like this.
x <- c("P2134.asfsafasfs","P0983.safdasfhdskjaf","8723.safhakjlfds")
I need to end up with:
"2134", "0983", and "8723"
Essentially, I need to extract the first four characters that are numbers from each element. Some begin with a letter (disallowing me from using a simple substring() function).
I guess technically, I could do something like:
x <- gsub("^P","",x)
x <- substr(x,1,4)
But I want to know how I would do this with regex!
You could use str_match from the stringr package:
library(stringr)
print(c(str_match(x, "\\d\\d\\d\\d")))
# [1] "2134" "0983" "8723"
You can do this with gsub too.
> sub('.?([0-9]{4}).*', '\\1', x)
[1] "2134" "0983" "8723"
>
I used sub instead of gsub to assure I only got the first match. .? says any single character and its optional (similar to just . but then it wouldn't match the case without the leading P). The () signify a group that I reference in the replacement '\\1'. If there were multiple sets of () I could reference them too with '\\2'. Inside the group, and you had the syntax correct, I want only numbers and I want exactly 4 of them. The final piece says zero or more trailing characters of any type.
Your syntax was working, but you were replacing something with itself so you wind up with the same output.
This will get you the first four digits of a string, regardless of where in the string they appear.
mapply(function(x, m) paste0(x[m], collapse=""),
strsplit(x, ""),
lapply(gregexpr("\\d", x), "[", 1:4))
Breaking it down into pieces:
What's going on in the above line is as follows:
# this will get you a list of matches of digits, and their location in each x
matches <- gregexpr("\\d", x)
# this gets you each individual digit
matches <- lapply(matches, "[", 1:4)
# individual characters of x
splits <- strsplit(x, "")
# get the appropriate string
mapply(function(x, m) paste0(x[m], collapse=""), splits, matches)
Another group capturing approach that doesn't assume 4 numbers.
x <- c("P2134.asfsafasfs","P0983.safdasfhdskjaf","8723.safhakjlfds")
gsub("(^[^0-9]*)(\\d+)([^0-9].*)", "\\2", x)
## [1] "2134" "0983" "8723"

Resources