Interpreted String Literals

An implementation of interpreted string literals, inspired by Python's Literal String Interpolation <> and Docstrings <> and Julia's Triple-Quoted String Literals <>.

CRAN_Status_Badge Travis-CI BuildStatus CoverageStatus AppVeyor BuildStatus


Glue offers interpreted string literals that are small, fast, and dependency-free. Glue does this by embedding R expressions in curly braces which are then evaluated and inserted into the argument string.


# Install the released version from CRAN:
# Install the development version from GitHub:
# install.packages("devtools")


Variables can be passed directly into strings.
name <- "Fred"
glue('My name is {name}.')
#> My name is Fred.
Long strings are broken by line and concatenated together.
name <- "Fred"
age <- 50
anniversary <- as.Date("1991-10-12")
glue('My name is {name},',
  ' my age next year is {age + 1},',
  ' my anniversary is {format(anniversary, "%A, %B %d, %Y")}.')
#> My name is Fred, my age next year is 51, my anniversary is Saturday, October 12, 1991.
Named arguments are used to assign temporary variables.
glue('My name is {name},',
  ' my age next year is {age + 1},',
  ' my anniversary is {format(anniversary, "%A, %B %d, %Y")}.',
  name = "Joe",
  age = 40,
  anniversary = as.Date("2001-10-12"))
#> My name is Joe, my age next year is 41, my anniversary is Friday, October 12, 2001.
glue_data() is useful with magrittr pipes.
`%>%` <- magrittr::`%>%`
head(mtcars) %>% glue_data("{rownames(.)} has {hp} hp")
#> Mazda RX4 has 110 hp
#> Mazda RX4 Wag has 110 hp
#> Datsun 710 has 93 hp
#> Hornet 4 Drive has 110 hp
#> Hornet Sportabout has 175 hp
#> Valiant has 105 hp
Or within dplyr pipelines
head(iris) %>%
  mutate(description = glue("This {Species} has a petal length of {Petal.Length}"))
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa
#>                             description
#> 1 This setosa has a petal length of 1.4
#> 2 This setosa has a petal length of 1.4
#> 3 This setosa has a petal length of 1.3
#> 4 This setosa has a petal length of 1.5
#> 5 This setosa has a petal length of 1.4
#> 6 This setosa has a petal length of 1.7
Leading whitespace and blank lines from the first and last lines are automatically trimmed.

This lets you indent the strings naturally in code.

    A formatted string
    Can have multiple lines
      with additional indention preserved
#> A formatted string
#> Can have multiple lines
#>   with additional indention preserved
An additional newline can be used if you want a leading or trailing newline.
  leading or trailing newlines can be added explicitly
#> leading or trailing newlines can be added explicitly
\\ at the end of a line continues it without a new line.
    A formatted string \\
    can also be on a \\
    single line
#> A formatted string can also be on a single line
A literal brace is inserted by using doubled braces.
name <- "Fred"
glue("My name is {name}, not {{name}}.")
#> My name is Fred, not {name}.
Alternative delimiters can be specified with .open and .close.
one <- "1"
glue("The value of $e^{2\\pi i}$ is $<<one>>$.", .open = "<<", .close = ">>")
#> The value of $e^{2\pi i}$ is $1$.
All valid R code works in expressions, including braces and escaping.

Backslashes do need to be doubled just like in all R strings.

  `foo}\`` <- "foo"
        '}\\'' # { and } in comments, single quotes
        \"}\\\"\" # or double quotes are ignored
        `foo}\\`` # as are { in backticks
#> foo
glue_sql() makes constructing SQL statements safe and easy

Use backticks to quote identifiers, normal strings and numbers are quoted appropriately for your backend.

con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
colnames(iris) <- gsub("[.]", "_", tolower(colnames(iris)))
DBI::dbWriteTable(con, "iris", iris)
var <- "sepal_width"
tbl <- "iris"
num <- 2
val <- "setosa"
  SELECT {`var`}
  FROM {`tbl`}
  WHERE {`tbl`}.sepal_length > {num}
    AND {`tbl`}.species = {val}
  ", .con = con)
#> <SQL> SELECT `sepal_width`
#> FROM `iris`
#> WHERE `iris`.sepal_length > 2
#>   AND `iris`.species = 'setosa'
# `glue_sql()` can be used in conjunction with parameterized queries using
# `DBI::dbBind()` to provide protection for SQL Injection attacks
 sql <- glue_sql("
    SELECT {`var`}
    FROM {`tbl`}
    WHERE {`tbl`}.sepal_length > ?
  ", .con = con)
query <- DBI::dbSendQuery(con, sql)
DBI::dbBind(query, list(num))
DBI::dbFetch(query, n = 4)
#>   sepal_width
#> 1         3.5
#> 2         3.0
#> 3         3.2
#> 4         3.1
# `glue_sql()` can be used to build up more complex queries with
# interchangeable sub queries. It returns `DBI::SQL()` objects which are
# properly protected from quoting.
sub_query <- glue_sql("
  FROM {`tbl`}
  ", .con = con)
  SELECT s.{`var`}
  FROM ({sub_query}) AS s
  ", .con = con)
#> <SQL> SELECT s.`sepal_width`
#> FROM `iris`) AS s
# If you want to input multiple values for use in SQL IN statements put `*`
# at the end of the value and the values will be collapsed and quoted appropriately.
glue_sql("SELECT * FROM {`tbl`} WHERE sepal_length IN ({vals*})",
  vals = 1, .con = con)
#> <SQL> SELECT * FROM `iris` WHERE sepal_length IN (1)
glue_sql("SELECT * FROM {`tbl`} WHERE sepal_length IN ({vals*})",
  vals = 1:5, .con = con)
#> <SQL> SELECT * FROM `iris` WHERE sepal_length IN (1, 2, 3, 4, 5)
glue_sql("SELECT * FROM {`tbl`} WHERE species IN ({vals*})",
  vals = "setosa", .con = con)
#> <SQL> SELECT * FROM `iris` WHERE species IN ('setosa')
glue_sql("SELECT * FROM {`tbl`} WHERE species IN ({vals*})",
  vals = c("setosa", "versicolor"), .con = con)
#> <SQL> SELECT * FROM `iris` WHERE species IN ('setosa', 'versicolor')
Optionally combine strings with +
x <- 1
y <- 3
glue("x + y") + " = {x + y}"
#> x + y = 4

Other implementations

Some other implementations of string interpolation in R (although not using identical syntax).

String templating is closely related to string interpolation, although not exactly the same concept. Some packages implementing string templating in R include.


glue 1.3.1


  • glue() now has a + method to combine strings.

Bugfixes and minor changes

  • glue_sql() now supports unquoting lists of Id objects.
  • glue_sql() now quotes characters with NAs appropriately (#115).
  • glue_sql() now quotes Dates appropriately (#98).
  • A potential protection error reported by rchk was fixed.

glue 1.3.0

Breaking changes

  • The evaluate() function has been removed. Changes elsewhere in glue made the implementation trivial so it was removed for clarities sake. Previous uses can be replaced by eval(parse(text = text), envir).

  • collapse() has been renamed to glue_collapse() to avoid namespace collisions with dplyr::collapse().


  • compare.glue() was added, to make it easier to use glue objects in testthat::expect_equal() statements.

  • glue_col() and glue_data_col() functions added to display strings with color.

Bugfixes and minor changes

  • Glue now throws an informative error message when it cannot interpolate a function into a string (#114, @haleyjeppson & @ijlyttle).

  • Glue now evaluates unnamed arguments lazily with delayedAssign(), so there is no performance cost if an argument is not used. (#83, @egnha).

  • Fixed a bug where names in the assigned expression of an interpolation variable would conflict with the name of the variable itself (#89, @egnha).

  • Do not drop the glue class when subsetting (#66).

  • Fix glue() and collapse() always return UTF-8 encoded strings (#81, @dpprdan)

glue 1.2.0

  • The implementation has been tweaked to be slightly faster in most cases.

  • glue() now has a .transformer argument, which allows you to use custom logic on how to evaluate the code within glue blocks. See vignette("transformers") for more details and example transformer functions.

  • glue() now returns NA if any of the results are NA and .na is NULL. Otherwise NA values are replaced by the value of .na.

  • trim() to use the trimming logic from glue is now exported.

  • glue_sql() and glue_data_sql() functions added to make constructing SQL statements with glue safer and easier.

  • glue() is now easier to use when used within helper functions such as lapply.

  • Fix when last expression in glue() is NULL.

glue 1.1.1

  • Another fix for PROTECT / REPROTECT found by the rchk static analyzer.

glue 1.1.0

  • Fix for PROTECT errors when resizing output strings.

  • glue() always returns 'UTF-8' strings, converting inputs if in other encodings if needed.

  • to() and to_data() have been removed.

  • glue() and glue_data() can now take alternative delimiters to { and }. This is useful if you are writing to a format that uses a lot of braces, such as LaTeX. (#23)

  • collapse() now returns 0 length output if given 0 length input (#28).


  • Fix glue() to admit . as an embedded expression in a string (#15, @egnha).

  • Added a file to track changes to the package.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


1.4.2 by Jim Hester, a year ago,

Report a bug at

Browse source code at

Authors: Jim Hester [aut, cre]

Documentation:   PDF Manual  

MIT + file LICENSE license

Imports methods

Suggests testthat, covr, magrittr, crayon, knitr, rmarkdown, DBI, RSQLite, R.utils, forcats, microbenchmark, rprintf, stringr, ggplot2, dplyr, withr, vctrs

Imported by CB2, CopernicusDEM, DAMisc, DSSAT, DataFakeR, DesignLibrary, DiagrammeR, DirectEffects, FAIRmaterials, FielDHub, GDPuc, GIFTr, Gmisc, GomoGomonoMi, JSmediation, PWFSLSmoke, PlanetNICFI, PooledCohort, RAQSAPI, RCT, RInno, ReviewR, Rnightly, SpatialKDE, TITAN2, TriDimRegression, VarBundle, VicmapR, WeibullFit, XKCDdata, activatr, adobeanalyticsr, adoptr, algo, almanac, alphavantager, ambiorix, anomalize, anybadger, anyflights, apisensr, appler, applicable, apyramid, aquodom, archive, areal, assemblerr, attachment, attrib, available, basedosdados, batata, bayesplot, bcdata, bench, bigrquery, biolink, biscale, bistablehistory, bjscrapeR, boxr, bridger, brinton, brms, brolgar, broom, bruceR, bsplus, bubblyr, buildr, bumbl, bupaR, bysykkel, cabinets, campfin, casen, cder, ceramic, cfbfastR, chronicle, cimir, cleanTS, cli, cliapp, clinDR, codebook, configr, conflr, connectwidgets, corx, covid19france, covid19india, covid19us, cronologia, crosstable, cubelyr, daiR, daqapo, datacleanr, datadogr, dbflobr, dbplyr, dccvalidator, dcurves, dials, did2s, didimputation, discAUC, disk.frame, distributions3, dittodb, dm, dockerfiler, dplyr, dr4pl, drawer, dtplyr, dynwrap, easyr, ech, edeaR, educationdata, edwards97, einsum, emayili, emoji, eph, epigraphdb, epikit, erify, exams.mylearn, exams2sakai, exuber, fabricerin, fastRG, fastText, fastai, fauxnaif, fdapaceShiny, ffscrapr, ffsimulator, fgeo, fgeo.analyze, fgeo.plot, fgeo.tool, fiery, fitbitViz, fitzRoy, flair, flipbookr, flipdownr, forestecology, forrel, funneljoin, fusen, gargle, geouy, geoviz, gfonts, ggHoriPlot, gganimate, ggip, ggmap, ggplot2, ggpol, ggpp, ggprism, ggpubr, ggshadow, ggside, ggspatial, gitignore, gluedown, gm, googleCloudVisionR, googledrive, googlesheets4, gridpattern, grobblR, gt, gtsummary, gwasforest, gwpcormapper, hardhat, hlidacr, hockeyR, html2R, httr2, humanize, hutilscpp, huxtable, i2dash, iNZightTS, iNZightTools, ibdsim2, icecream, icesTAF, impactflu, impactr, infer, insane, isaeditor, isoreader, jaggR, joyn, jsontools, kableExtra, keras, kokudosuuchi, latte, levitate, lidR, lifecycle, luz, lvmisc, mailmerge, mailtoR, meshed, messaging, metabolic, metaconfoundr, meteospain, microservices, mlbstatsR, mlflow, modelsummary, modeltime, modeltime.ensemble, modeltime.gluonts, modeltime.h2o, modeltime.resample, moderndive, moexer, moodleR, mosaic, mrgsolve, mudata2, multicolor, multinma, namer, nandb, naniar, neo4r, nfl4th, nflfastR, nflseedR, numform, odin, onelogin, optimall, oysteR, pak, params, parsnip, pathlibr, peRspective, pedbuildr, personalr, photosynthesis, pins, pkgcache, pkgdepends, pkgnet, plumbertableau, pocketapi, pointblank, poissonreg, processcheckR, processmapR, psycModel, ptvapi, qsub, qualmap, qualtRics, quincunx, r2dii.analysis, r2dii.match, r2dii.plot, r2pptx, r6methods, rKolada, rRofex,, radous, rando, rangeMapper, raveio, rcol, readabs, recipes, regions, reprex, reproducible, retroharmonize, rextendr, rfinance, ribd, ricu, riingo, rintimg, rmonad, rock, romic, ropenblas, rscopus, rticulate, rtodoist, rtypeform, safejoin, sapfluxnetr, savonliquide, scrollrevealR, segmentr, semantic.dashboard, seminr, sendgridr,, shiny, shiny.i18n,, shiny.react, shiny.semantic, shinyauthr, shinycssloaders, shinycustomloader, shinydisconnect, shinyobjects, shinypanels, shinyvalidate, sift, simstudy, sitar, sketch, slider, sparklyr, specr, sportyR, spsComps, spsUtil, stacks, staplr, starter, statsearchanalyticsr, stringr, styler, sudachir, table.glue, tabnet, taylor, tealeaves, textclean, tibbletime, tidyRSS, tidycode, tidycomm, tidyestimate, tidylog, tidyr, tidyselect, tidysmd, tidytable, tidywikidatar, tipr, togglr, torchaudio, trainR, traineR, trip, tsibbletalk, tune, tvthemes, upstartr, usethis, varsExplore, vctrs, vdiffr, vegawidget, vembedr, visdat, vitae, vizdraws, votesmart, vov, vroom, waldo, walmartAPI, wikipediatrend, workflowr, workflows, wrappedtools, xaringanthemer, xgxr, ymlthis.

Depended on by iCARH.

Suggested by DBI, DGEobj, DGEobj.utils, SingleCaseES, admixr, bcmaps, bigsnpr, blastula, broom.helpers, canvasXpress, cpp11, dashboardthemes, detrendr, devtoolbox, dipsaus, faux, ggtext, ggthemes, golem, healthyR.ts, htmlTable, industRial, interactions, lgr, logger, mdthemes, mrf2d, precommit, presser, rbenvo, rlang, rvest, scdhlm, shinyloadtest, simplevis, survivoR, syn, tidymodels, tidyverse, torch, unglue, unusualprofile, visR, webfakes, wpa.

See at CRAN