writeLines() not producing a valid makefile - r

I'm trying to auto-generate a makefile using R, and have run into a very peculiar problem.
The makefile is produced using the following code:
v <- "histogram.tsv: histogram.r\r\tRscript histogram.r"
fileConn <- file("Makefile")
writeLines(v, fileConn)
close(fileConn)
This produces the following Makefile
histogram.tsv: histogram.r
Rscript histogram.r
This Makefile doesn't build, but when I manually type in the Tab before "Rscript" it does! When I compare the text generated by write.lines to that generated by hand, identical() returns TRUE.

It works fine when I test it on Linux Mint. It's probable that your distribution is not forgiving when it comes to carriage return characters, typically used in windows. You can try removing the carriage return characters or use dos2unix:
In DOS/Windows text files a line break, also known as newline, is a
combination of two characters: a Carriage Return (CR) followed by a
Line Feed (LF). In Unix text files a line break is a single character:
the Line Feed (LF). In Mac text files, prior to Mac OS X, a line break
was single Carriage Return (CR) character. Nowadays Mac OS uses Unix
style (LF) line breaks.
sudo apt-get install dos2unix
dos2unix Makefile
In your case, you'd also need to insert a newline character, hence set v as follows:
v <- "histogram.tsv: histogram.r\n\tRscript histogram.r"
You can try a messier way of writing the makefile, in order to avoid such sort of problems:
target: dependencies; \
command1; \
command2

Related

.REnviron with special characters

I am having trouble trying to add environment variables to a REnviron file that have special characters. This is on a Debian machine with the file located at /usr/lib/R/etc/Renviron. If my value has a &, I get a weird error when installing packages (although the package installs fine):
REnviron file: TEST_KEY=HEY&X&THERE
Command: install.packages(futures)
Error:
/usr/lib/R/bin/Rcmd: 468: /usr/lib/R/etc/Renviron: THERE: not found
/usr/lib/R/bin/Rcmd: 468: /usr/lib/R/etc/Renviron: X: not found
Which seems like it's because & is a special character. I can fix this by putting quotes around the value like this: TEST_KEY="HEY&X&THERE". However at that point I can't figure out how to handle when a value itself has a " in it. For example if I wanted the value to be HEY&"&THERE I am not sure how to format that (a backlash in front of the quote didn't work). I tried "HEY&\"&THERE", but that left the \ in the string once loaded into R. Which leads me to my broader question:
How can I ensure that anything that satisfies linux environment variable styling rules works in an REnviron file?
Update: this seems to be a Debian specific issue. You can recreate it using the debian:bullseye-slim docker image, installing R, then editing the Renviron to have a & in it.
Okay I spent an hour looking into this and I think there is the answer.
In both Ubuntu and Debian (and maybe other systems too), the Renviron file gets executed within bash. So what you're typing in the file is exactly bash commands. You can see in lines 39-40 of RCmd the commands:
. "${R_HOME}/etc${R_ARCH}/Renviron"
export `sed 's/^ *#.*//; s/^\([^=]*\)=.*/\1/' "${R_HOME}/etc${R_ARCH}/Renviron"`
The first line runs the Renviron file in the shell, the second then exports the variable names based on lines that have a = in them.
So in our case the way to handle this is to put double quotations around all the values, and any double-quote within the string should get a \ before it. The reason why I didn't realize the solution before I posted the question is that I didn't use cat() when printing my text in R, which removes the leading \. So: "HEY&\"&THERE" would be the right way to do it.
To recap:
The Renviron file is executed on the shell
To handle special characters in strings you use the same logic you would in the OS (so double quotes with \ to escape actual double quotes).

Saving complex text string as an object in R

I'm trying to run this terminal command from within R using system(mess):
mess <- "sed -i -e '62i\ \\\usepackage[margin=2cm]{geometry}' intro-spatial-rl.tex"
But it keeps failing with the following error:
Error: '\u' used without hex digits in character string starting ""sed -i -e '62i\ \\\u"
I've seen paste used for system commands also, but this fails also.
Could use a different regex program, but thought this may be useful to others and improve my understanding of how R deals with characters. Thank you!
Your problem is the unequal number of \ in your escape sequence.
R sees two escape sequences here: \\ and \u. The second one is invalid and gives an error. You probably want to escape the second backslash as well, yielding \\\\. Likewise, you probably meant to escape the previous \ in \ as well, leaving you with \\ .
All that being said, would replace the sed invocation completely by R code in this instance. The way I understand it you just want to insert a line of text. That’s easy in R (although it’s not clear what your input and output here is).

Executing expressions in Rscript.exe

I'd like to put some expressions that write stuff to a file directly into a call to Rscript.exe (without specifying file in Rscript [options] [-e expression] file [args] and thus without an explicit R script that is run).
Everything seems to work except the fact that the desired file is not created. What am I doing wrong?
# Works:
shell("Rscript -e print(Sys.time())")
# Works:
write(Sys.time(), file='c:/temp/systime.txt')
# No error, but no file created:
shell("Rscript -e write(Sys.time(), file='c:/temp/systime.txt')")
Rscript parses its command line using spaces as separators. If your R string contains embedded spaces, you need to wrap it within quotes to make sure it gets sent as a complete unit to the R parser.
You also don't need to use shell unless you specifically need features of cmd.exe.
system("Rscript.exe -e \"write(Sys.time(), file='c:/temp/systime.txt')\"")

How to save a text file with noeol and in dos format using vi on a linux system

I am running the IBAMR model (a set of codes for solving immersed boundary problems) on x86_64 GNU/Linux.
The startup configuration file is called input2d.
When I open it with vi, I find:
"input2d" [noeol][dos] 251L, 11689C
If I compile the IBAMR model without saving input2d, it compiles and runs fine.
However, if I save input2d, the compiler crashes, saying:
Warning in input2d at line 251 column 5 : Illegal character token in input
Clearly this has something to do with unix adding a newline to the end of the file.
Here's my question:
How do I save this file in dos format AND without a trailing newline in vi on a unix system?
Use vim -b <file> or :set binary to tell vim not to append an newline at the end of the file. From :help binary:
When writing a file the <EOL> for the last line is only written if
there was one in the original file (normally Vim appends an <EOL> to
the last line if there is none; this would make the file longer). See
the 'endofline' option.
There's a script for this that I found on Vim Tips:
http://vim.wikia.com/wiki/Preserve_missing_end-of-line_at_end_of_text_files
It automatically enables "binary" if there was no eol, but ensures the original line-endings are preserved for the rest of the file.

simple shell script in cygwin

#!/bin/bash
echo 'first line' >foo.xml
echo 'second line' >>foo.xml
I am a total newbie to shell scripting.
I am trying to run the above script in cygwin. I want to be able to write one line after the other to a new file.
However, when I execute the above script, I see the follwoing contents in foo.xml:
second line
The second time I run the script, I see in foo.xml:
second line
second line
and so on.
Also, I see the following error displayed at the command prompt after running the script:
: No such file or directory.xml
I will eventually be running this script on a unix box, I am just trying to develop it using cygwin. So I would appreciate it if you could point out if it is a cygwin oddity and if so, should I avoid trying to use cygwin for development of such scripts?
Thanks in advance.
Run dos2unix on your shell script. That will fix the problem.
I had the same kind of problem as the original poster: A very simple script file was not working in Cygwin.
Thanks to Don Branson for the clue.
The fix for me was built into the text editor I'm using. (Most programmer's editors have a feature like this.) For example, in my case I'm using Notepad++, which has a menu item to convert the file line endings to Unix-style. From the menu: [Edit]->[EOL Conversion]->[Unix (LF)]
Then the script behaved as expected.
But there must be something else that is wrong here. When I try it, it works as expected.
> foo.xml puts the line into foo.xml, replacing any previous contents.
>> foo.xml appends to file
It sounds like you may have a typo somewhere. Also keep in mind that while the Windows command prompt can be forgiving about paths with embedded spaces, cygwin's shells will not be, so if you have a filename that contains embedded spaces, you need to either quote the filename or escape the spaces:
echo 'first line' > 'My File.txt'
echo 'first line' > My\ File.txt
The same goes for certain "special" characters including quotes, ampersand (&), semicolons (;) and generally most punctuation other than period/full-stop (.).
So if you are seeing those issues using the exact script that you are running (i.e. you copy and pasted it, there is no possibility of transcription errors) then something truly strange may be happening that I can't explain. Otherwise, there may be a misplaced space or unquoted character somewhere.
I cannot reproduce your results. The script you quote looks correct, and indeed works as expected in my installation of Cygwin here, producing the file foo.xml containing the lines first line and second line; implying that what you are actually running differs from what you quoted in some way that is causing the problem.
The error message implies some sort of problem with the filename in the first echo line. Do you have some nonprintable characters in the script you are running? Have you missed escaping a space in the filename? Are you subsituting shell variables and mistyping the name of the variable or failing to escape the resulting string?
The above should work normally..
However you can always specify a heredoc:
#!/bin/bash
cat <<EOF > foo.xml
first line
second line
EOF

Resources