在R中是否有类似于" here document"在bash?

时间:2015-08-02 09:29:38

标签: r

我的脚本包含

lines <- readLines("~/data")

我想在脚本本身保留文件数据的内容(逐字)。是否存在R a&#34; read_the_following_lines&#34;功能?喜欢&#34; here document&#34;在bash shell中?

4 个答案:

答案 0 :(得分:4)

多行字符串将尽可能接近。它绝对不一样(因为你必须关心引号)但是它确实适用于你想要实现的目标(并且你可以用超过read.table来完成它):

here_lines <- 'line 1
line 2
line 3
'

readLines(textConnection(here_lines))

## [1] "line 1" "line 2" "line 3" ""


here_csv <- 'thing,val
one,1
two,2
'

read.table(text=here_csv, sep=",", header=TRUE, stringsAsFactors=FALSE)

##   thing val
## 1   one   1
## 2   two   2


here_json <- '{
"a" : [ 1, 2, 3 ],
"b" : [ 4, 5, 6 ],
"c" : { "d" : { "e" : [7, 8, 9]}}
}
'

jsonlite::fromJSON(here_json)

## $a
## [1] 1 2 3
## 
## $b
## [1] 4 5 6
## 
## $c
## $c$d
## $c$d$e
## [1] 7 8 9

here_xml <- '<CATALOG>
<PLANT>
<COMMON>Bloodroot</COMMON>
<BOTANICAL>Sanguinaria canadensis</BOTANICAL>
<ZONE>4</ZONE>a
<LIGHT>Mostly Shady</LIGHT>
<PRICE>$2.44</PRICE>
<AVAILABILITY>031599</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Columbine</COMMON>
<BOTANICAL>Aquilegia canadensis</BOTANICAL>
<ZONE>3</ZONE>
<LIGHT>Mostly Shady</LIGHT>
<PRICE>$9.37</PRICE>
<AVAILABILITY>030699</AVAILABILITY>
</PLANT>
</CATALOG>
'

str(xml <- XML::xmlParse(here_xml))

## Classes 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr>

print(xml)

## <?xml version="1.0"?>
## <CATALOG>
##   <PLANT><COMMON>Bloodroot</COMMON><BOTANICAL>Sanguinaria canadensis</BOTANICAL><ZONE>4</ZONE>a
## <LIGHT>Mostly Shady</LIGHT><PRICE>$2.44</PRICE><AVAILABILITY>031599</AVAILABILITY></PLANT>
##   <PLANT>
##     <COMMON>Columbine</COMMON>
##     <BOTANICAL>Aquilegia canadensis</BOTANICAL>
##     <ZONE>3</ZONE>
##     <LIGHT>Mostly Shady</LIGHT>
##     <PRICE>$9.37</PRICE>
##     <AVAILABILITY>030699</AVAILABILITY>
##   </PLANT>
## </CATALOG>

答案 1 :(得分:0)

第90f页。 An introduction to R表示可以像这样编写R脚本(我引用从那里修改的示例):

chem <- scan()
2.90 3.10 3.40 3.40 3.70 3.70 2.80 2.50 2.40 2.40 2.70 2.20
5.28 3.37 3.03 3.03 28.95 3.77 3.40 2.20 3.50 3.60 3.70 3.70

print(chem)

将这些行写入文件,并为其命名,例如heredoc.R。如果您通过键入终端

以非交互方式执行该脚本
Rscript heredoc.R

您将获得以下输出

Read 24 items
 [1]  2.90  3.10  3.40  3.40  3.70  3.70  2.80  2.50  2.40  2.40  2.70  2.20
[13]  5.28  3.37  3.03  3.03 28.95  3.77  3.40  2.20  3.50  3.60  3.70  3.70

因此,您会看到文件中提供的数据保存在变量chem中。函数scan(.)默认从连接stdin()读取。 stdin()是指以交互模式从控制台输入的用户输入(在没有指定脚本的情况下调用R),但是当读入输入脚本时,将读取该脚本的以下行*)。数据之后的空行很重要,因为它标记了数据的结束。

这也适用于表格数据:

tab <- read.table(file=stdin(), header=T)
A B C
1 1 0
2 1 0
3 2 9

summary(tab)

使用readLines(.)时,必须指定读取的行数;空行的方法在这里不起作用:

txt <- readLines(con=stdin(), n=5)                                             
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ultricies diam   
sed felis mattis, id commodo enim hendrerit. Suspendisse iaculis bibendum eros, 
ut mattis eros interdum sit amet. Pellentesque condimentum eleifend blandit. Ut 
commodo ligula quis varius faucibus. Aliquam accumsan tortor velit, et varius   
sapien tristique ut. Sed accumsan, tellus non iaculis luctus, neque nunc        

print(txt) 

您可以通过一次读取一行直到一行为空或其他预定义字符串来克服此限制。但请注意,如果以这种方式读取大型(> 100MB)文件,则可能内存不足,因为每次将字符串附加到读入数据时, all 都会复制数据到记忆中的另一个地方。请参阅The R inferno中的“成长对象”一章:

txt <- c()
repeat{
    x <- readLines(con=stdin(), n=1)
    if(x == "") break # you can use any EOF string you want here
    txt = c(txt, x)
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ultricies diam
sed felis mattis, id commodo enim hendrerit. Suspendisse iaculis bibendum eros,
ut mattis eros interdum sit amet. Pellentesque condimentum eleifend blandit. Ut
commodo ligula quis varius faucibus. Aliquam accumsan tortor velit, et varius
sapien tristique ut. Sed accumsan, tellus non iaculis luctus, neque nunc

print(txt)

*)如果要读取R脚本中的标准输入,例如,因为您要创建可重用的脚本,可以使用任何输入数据(Rscript reusablescript.R < input.txtsome-data-generating-command | Rscript reusablescript.R),请勿使用stdin()file("stdin")

答案 2 :(得分:0)

一种做多行字符串的方法,但不用担心你可以使用的引号(只有反引号):

as.character(quote(`
all of the crazy " ' ) characters, except 
backtick and bare backslashes that aren't 
printable, e.g. \n works but a \ and c with no space between them would fail`))

答案 3 :(得分:0)

从 R v4.0.0 开始,原始字符串有了新的语法 as stated in changelogs,它在很大程度上允许创建 heredocs 样式的文档。

此外,来自help(Quotes)

<块引用>

还可以使用分隔符对 [] 和 {},并且可以使用 R 代替 r。为了增加灵活性,可以在开始引号和开始分隔符之间放置多个破折号,只要结束分隔符和结束引号之间出现相同数量的破折号即可。

例如,可以使用(在具有 BASH shell 的系统上):

file_raw_string <-
r"(#!/bin/bash
echo $@
for word in $@;
do
  echo "This is the word: '${word}'."
done
exit 0
)"

writeLines(file_raw_string, "print_words.sh")

system("bash print_words.sh Word/1 w@rd2 LongWord composite-word")

甚至另一个 R 脚本:

file_raw_string <- r"(
x <- lapply(mtcars[,1:4], mean)
cat(
  paste(
    "Mean for column", names(x), "is", format(x,digits = 2),
    collapse = "\n"
  )
)
cat("\n")
cat(r"{ - This is a raw string where \n, "", '', /, \ are allowed.}")
)"

writeLines(file_raw_string, "print_means.R")

source("print_means.R")

#> Mean for column mpg is 20
#> Mean for column cyl is 6.2
#> Mean for column disp is 231
#> Mean for column hp is 147
#>  - This is a raw string where \n, "", '', /, \ are allowed.

reprex package (v2.0.0) 于 2021 年 8 月 1 日创建