find_replace nul character in R

Viewed 190

the only thing that seams to be the closest to my problem is: are-there-raw-strings-in-r However this does not help me enough.

The problem

I have a Windows-like formatted paths in a data frame:

data.frame(path = c("X:\01_aim\01_seq.R", "X:\01_aim\02_seq.R", "X:\01_aim\03_seq.R"), 
           dat = c("data1.csv", "data2.csv", "data1.csv"))

The aim is to convert the paths into Unix like path, thus I need an output like:

data.frame(path = c("/01_aim/01_seq.R", "/01_aim/02_seq.R", "/01_aim/03_seq.R"), 
           dat = c("data1.csv", "data2.csv", "data1.csv"))

My approach

An approach to manipulate paths you see above generates the following error:

> sub("\0", "##", "X:\01_aim\01_seq.R")
# Error: nul character not allowed (line 1)

What I found already is the way to print the path using r"()" formatting option, which gives:

> r"(X:\01_aim\01_seq.R)"
[1] "X:\01_aim\01_seq.R"

With that my final solution would be close to:

tmp_path <- str_replace_all(string = r"(X:\01_aim\01_seq.R)",      
    pattern = r"(\\)", 
    replacement =  "/")
str_replace_all(tmp_path, r"(X:)", "")
[1] "/01_aim/01_seq.R"

but what I lack is how to force the r"( )" formatting of a string on a given string in a variable. Specifically, when I have a function:

convert.path <- function(my.path){
   # how can I force the variable my.path to be stored as r"(`my.path`)"
   # so that I can insert the above code here.
   my.path.raw <- to.r.brackets(my.path)
   tmp_path <- str_replace_all(my.path.raw, pattern = r"(\\)", replacement =  "/")
   str_replace_all(tmp_path, r"(X:)", "")
}

I wanted to force re-formatting in place of comments. Does anyone have an idea how to make this trick?

1 Answers

One way is to use gsub() within eval(parse(text = ...)):

dat <- data.frame(path = c("X:\01_aim\01_seq.R", "X:\01_aim\02_seq.R", "X:\01_aim\03_seq.R", "X:\01_aim\04_seq.R"), 
                  dat = c("data1.csv", "data2.csv", "data1.csv", "data2.csv"))

temp <- eval(parse(text= gsub("\\", "/", deparse(dat$path), fixed=TRUE)))
gsub("X:", "", temp)

#> [1] "/001_aim/001_seq.R" "/001_aim/002_seq.R" "/001_aim/003_seq.R"
#> [4] "/001_aim/004_seq.R"

Created on 2021-08-23 by the reprex package (v2.0.1)

Another way is to escape the strings containing one backslash using stringi::stri_escape_unicode. Since the string is converted to unicode before being escaped this adds an unwanted u0 after each pair of backslashs. We can then use gsub("\\\\u0", "/") to get the desired file path.

dat <- data.frame(path = c("X:\01_aim\01_seq.R", "X:\01_aim\02_seq.R", "X:\01_aim\03_seq.R"), 
           dat = c("data1.csv", "data2.csv", "data1.csv"))


temp <- gsub("X:", "", stringi::stri_escape_unicode(dat$path))
gsub("\\\\u0", "/", temp)
#> [1] "/001_aim/001_seq.R" "/001_aim/002_seq.R" "/001_aim/003_seq.R"

Created on 2021-08-23 by the reprex package (v2.0.1)

Related