166

I want to split a line in an R script over multiple lines (because it is too long). How do I do that?

Specifically, I have a line such as

setwd('~/a/very/long/path/here/that/goes/beyond/80/characters/and/then/some/more')

Is it possible to split the long path over multiple lines? I tried

setwd('~/a/very/long/path/here/that/goes/beyond/80/characters/and/
then/some/more')

with return key at the end of the first line; but that does not work.

Thanks.

smci
  • 32,567
  • 20
  • 113
  • 146
Curious2learn
  • 31,692
  • 43
  • 108
  • 125

9 Answers9

178

Bah, comments are too small. Anyway, @Dirk is very right.

R doesn't need to be told the code starts at the next line. It is smarter than Python ;-) and will just continue to read the next line whenever it considers the statement as "not finished". Actually, in your case it also went to the next line, but R takes the return as a character when it is placed between "".

Mind you, you'll have to make sure your code isn't finished. Compare

a <- 1 + 2
+ 3

with

a <- 1 + 2 +
3

So, when spreading code over multiple lines, you have to make sure that R knows something is coming, either by :

  • leaving a bracket open, or
  • ending the line with an operator

When we're talking strings, this still works but you need to be a bit careful. You can open the quotation marks and R will read on until you close it. But every character, including the newline, will be seen as part of the string :

x <- "This is a very
long string over two lines."
x
## [1] "This is a very\nlong string over two lines."
cat(x)
## This is a very
## long string over two lines.

That's the reason why in this case, your code didn't work: a path can't contain a newline character (\n). So that's also why you better use the solution with paste() or paste0() Dirk proposed.

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
Joris Meys
  • 106,551
  • 31
  • 221
  • 263
  • Thanks Joris. I saw the examples similar to the ones you have given in the some online documentation and tried that for the string too. I thought that if it does not encounter a closing quote, it will continue to the next line. But with string it does not work, or rather, as you said, works in a different way in the sense that it take enter as a new line character. – Curious2learn Jun 13 '11 at 22:30
  • Thanks for making it clear why *sometimes* you can split lines with a plus sign! – Iain Samuel McLean Elder Mar 08 '14 at 20:34
  • Often a [nuisance with long multiline ggplot commands](http://stackoverflow.com/a/22731369/202229) – smci Mar 29 '14 at 12:58
  • 16
    no, it's not smarter than python here. rather than `paste("~one",\n"/two")` you just need `("~one" \n "/two")`. drop the commas and the `paste`. Not looking language smackdown. I use both languages but have always though paste was an annoyance. – Phil Cooper Apr 12 '16 at 23:01
  • @PhilCooper I wasn't refering to paste. It was a lighthearted joke. I use both R and Python, and each shines in different areas. I was just refering to the fact that you need `\\` in Python to split a line. – Joris Meys Apr 13 '16 at 08:56
  • 2
    @JorisMeys Right, I was trying to correct that misstatement. Use parens and you don't need the "\" for line continuation. I like it because you can also have comments on lines which you cannot do with the "\" syntax (e.g. `("one"\n "/one.one" # some comment\n "/two")'` examples in http://stackoverflow.com/questions/10660435/pythonic-way-to-create-a-long-multi-line-string – Phil Cooper Apr 13 '16 at 13:22
  • 1
    `leaving a bracket open, or ending the line with an operator` these two are the way to go. – Learner Mar 13 '17 at 09:00
136

You are not breaking code over multiple lines, but rather a single identifier. There is a difference.

For your issue, try

R> setwd(paste("~/a/very/long/path/here",
               "/and/then/some/more",
               "/and/then/some/more",
               "/and/then/some/more", sep=""))

which also illustrates that it is perfectly fine to break code across multiple lines.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
38

Dirk's method above will absolutely work, but if you're looking for a way to bring in a long string where whitespace/structure is important to preserve (example: a SQL query using RODBC) there is a two step solution.

1) Bring the text string in across multiple lines

long_string <- "this
is 
a 
long
string
with
whitespace"

2) R will introduce a bunch of \n characters. Strip those out with strwrap(), which destroys whitespace, per the documentation:

strwrap(long_string, width=10000, simplify=TRUE)

By telling strwrap to wrap your text to a very, very long row, you get a single character vector with no whitespace/newline characters.

Andrew
  • 9,090
  • 8
  • 46
  • 59
  • 3
    I like this answer most because I don't have to write so many commas as with paste, if the string is rather long. +1 – user3032689 Jun 20 '16 at 20:55
  • 5
    Be aware that `strwrap` might return vector of multiple strings even if source string doesn't exceed 10k characters. Try `strwrap("a\n\nb")`. It will return vector of length 3 and you need to paste it back using `paste(strwrap("a\n\nb"), collapse=" ")` using a space character glue to collapse vector. – Gedrox Sep 30 '16 at 08:48
  • Can someone edit the answer to include the important information in the previous comment? I do not quite understand the issue and do not want to mess up the answer. – randy Dec 20 '21 at 22:34
  • I do not understand what “where whitespace/structure is important to preserve” means here. Does that mean preserved in the code or in the character object itself? Also, the resulting character vector definitely does have whitespace. I understand this answer to be about how to replace line breaks with spaces and then collapse each case of whitespace to a single space (except that double spaces after some punctuation are preserved). – randy Dec 20 '21 at 22:49
24

For that particular case there is file.path :

File <- file.path("~", 
  "a", 
  "very", 
  "long",
  "path",
  "here",
  "that",
  "goes",
  "beyond",
  "80",
  "characters",
  "and",
  "then",
  "some",
  "more")
setwd(File)
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
7

I know this post is old, but I had a Situation like this and just want to share my solution. All the answers above work fine. But if you have a Code such as those in data.table chaining Syntax it becomes abit challenging. e.g. I had a Problem like this.

mass <- files[, Veg:=tstrsplit(files$file, "/")[1:4][[1]]][, Rain:=tstrsplit(files$file, "/")[1:4][[2]]][, Roughness:=tstrsplit(files$file, "/")[1:4][[3]]][, Geom:=tstrsplit(files$file, "/")[1:4][[4]]][time_[s]<=12000]

I tried most of the suggestions above and they didn´t work. but I figured out that they can be split after the comma within []. Splitting at ][ doesn´t work.

mass <- files[, Veg:=tstrsplit(files$file, "/")[1:4][[1]]][, 
    Rain:=tstrsplit(files$file, "/")[1:4][[2]]][, 
    Roughness:=tstrsplit(files$file, "/")[1:4][[3]]][, 
    Geom:=tstrsplit(files$file, "/")[1:4][[4]]][`time_[s]`<=12000]
M Terry
  • 173
  • 1
  • 7
  • Could it be you mixed up the question you were trying to answer? This has nothing to do with OP's question. – zerweck May 19 '20 at 06:44
  • 1
    It does have. The main question is how to split a line of code into several lines. I demonstrated that by using another example which is abit more complex than the original question. I thought it was necessary to post it because I spent a lot of time trying to figure out how to split that particular piece of code. And I guess it help someone with a similar problem. – M Terry May 20 '20 at 08:10
  • The OP's problem was that splitting a character vector with a linebreak includes the linebreak in the character vector. Your answer is only specific to data.table syntax – zerweck May 20 '20 at 08:54
  • As an example of splitting a line of code over multiple lines – M Terry May 21 '20 at 10:58
  • This answer is within the scope of the question because the question is unclear. Some people know that writing a single-line string across multiple lines is a special case that deserves a separate question from how to split lines of code in general, but many of the people who will see this question do not know that. Ideally, there would be two different questions that each contained a link to the other, but there are already answers to both questions here. – randy Dec 20 '21 at 22:31
  • This is a useful answer, in scope for the general question as asked (although not the OP's particular example). A naive Google search for the general question brings up this page and it is helpful to have this solution here. Even though it is really ugly! The empty-comma syntax of data.table is bad enough, but splitting a line at it is just horrible for legible code. – HTFB Mar 09 '23 at 12:06
7

The glue::glue function can help. You can write a string on multiple lines in a script but remove the line breaks from the string object by ending each line with \\:

glue("some\\
     thing")

something
randy
  • 1,031
  • 10
  • 20
Álvaro
  • 564
  • 5
  • 13
2

I do this all of the time. Use the paste0() function.

Rootdir = "/myhome/thisproject/part1/"
Subdir = "subdirectory1/subsubdir2/"

fullpath = paste0( Rootdir, Subdir )

fullpath

> fullpath
[1] "/myhome/thisproject/part1/subdirectory1/subsubdir2/"

bbneo
  • 29
  • 5
1

There is no coinvent way to do this because there is no operator in R to do string concatenation.

However, you can define a R Infix operator to do string concatenation:

`%+%` = function(x,y) return(paste0(x,y))

Then you can use it to concat strings, even break the code to multiple lines:

s = "a" %+%
    "b" %+%
    "c"

This will give you "abc".

Feng Jiang
  • 1,776
  • 19
  • 25
0

This will keep the \n character, but you can also just wrap the quote in parentheses. Especially useful in RMarkdown.

t <- ("
this is a long
string
")
Kyouma
  • 320
  • 6
  • 14
  • What are the parentheses doing? I have not found any effect of including or omitting them. This also does not seem to be answering the question, which is about how to write a single-line string over multiple lines of a script. – randy Dec 20 '21 at 22:26