Ta odpowiedź używa wyrażeń regularnych. Istnieje kilka przypadków skrajnych, w których zawiedzie, ale powinno być w porządku dla większości kodu. Jeśli potrzebujesz doskonałego dopasowania, musisz użyć parsera, ale w razie napotkania problemów możesz zawsze poprawić wyrazy regularne.
Uważaj na
#quoted function names
`my cr*azily*named^function!`(x = 1:10)
#Nested brackets inside functions
mean(x = (3 + 1:10))
#assignments inside if or for blocks
if((x = 10) > 3) cat("foo")
#functions running over multiple lines will currently fail
#maybe fixable with paste(original_code, collapse = "\n")
mean(
x = 1:10
)
Kod jest oparte na przykład na stronie ?regmatches
. Podstawową ideą jest: zamiana zawartości funkcji na element zastępczy, dokonanie wymiany, a następnie powrót do zawartości funkcji.
#Sample code. For real case, use
#readLines("source_file.R")
original_code <- c("a = 1", "b = mean(x = 1)")
#Function contents are considered to be a function name,
#an open bracket, some stuff, then a close bracket.
#Here function names are considered to be a letter or
#dot or underscore followed by optional letters, numbers, dots or
#underscores. This matches a few non-valid names (see ?match.names
#and warning above).
function_content <- gregexpr(
"[[:alpha:]._][[:alnum:._]*\\([^)]*\\)",
original_code
)
#Take a copy of the code to modify
copy <- original_code
#Replace all instances of function contents with the word PLACEHOLDER.
#If you have that word inside your code already, things will break.
copy <- mapply(
function(pattern, replacement, x)
{
if(length(pattern) > 0)
{
gsub(pattern, replacement, x, fixed = TRUE)
} else x
},
pattern = regmatches(copy, function_content),
replacement = "PLACEHOLDER",
x = copy,
USE.NAMES = FALSE
)
#Replace = with <-
copy <- gsub("=", "<-", copy)
#Now substitute back your function contents
(fixed_code <- mapply(
function(pattern, replacement, x)
{
if(length(replacement) > 0)
{
gsub(pattern, replacement, x, fixed = TRUE)
} else x
},
pattern = "PLACEHOLDER",
replacement = regmatches(original_code, function_content),
x = copy,
USE.NAMES = FALSE
))
#Write back to your source file
#writeLines(fixed_code, "source_file_fixed.R")
Dobry i użyteczny kod open-source nie umiera i nigdy nie zaginie w nim - a teraz parser ma nowego opiekuna, jak można się spodziewać. Gdzie dokładnie jest problem w zależności od testowanego narzędzia, które wykonuje zadanie? –
Na pewno mam zaufanie do Andrew, a społeczność nie pozwoli, by parser umarł. W rzeczywistości chciałem (https://github.com/yihui/knitr/issues/211) usunąć zależność od highlight/parser, zanim zostały osierocone; nie jest to wartość zależna od tej stosunkowo małej funkcji (długi łańcuch zależności ma problemy, takie jak konserwacja i czas ładowania pakietu). –
Po co zawracać sobie głowę? I dlaczego pytanie o zastąpienie "=" przez "<-", gdy preferujesz pierwsze? – mdsumner