2012-06-09 9 views
24

Estoy ejecutando Ubuntu 11.10 y me gustaría poder escribir en el portapapeles (o la selección principal). A continuación se presenta un error¿Cómo escribir en el portapapeles en Ubuntu/Linux en R?

> x <- 1:10 
> dput(x, 'clipboard') 
Error in file(file, "wt") : 'mode' for the clipboard must be 'r' on Unix 

¿Cómo puedo escribir en el portapapeles de selección/primaria?

Tenga en cuenta que he visto this old R-Help post, pero todavía no estoy seguro de lo que debería hacer.

Linux no tiene un portapapeles, pero una sesión X11 tiene primarias y selecciones secundarias. ? Archivo dice

portapapeles:

'file' can also be used with 'description = "clipboard"' in mode 
    '"r"' only. It reads the X11 primary selection, which can also be 
    specified as '"X11_primary"' and the secondary selection as 
    '"X11_secondary"'. 

    When the clipboard is opened for reading, the contents are 
    immediately copied to internal storage in the connection. 

    Unix users wishing to _write_ to the primary selection may be able 
    to do so via 'xclip' (<URL: 
    http://people.debian.org/~kims/xclip/>), for example by 
    'pipe("xclip -i", "w")'. 

por lo RTFM aplicada. Escribir en una selección X11 necesita múltiples hilos y no creo que valga la pena el esfuerzo considerable de implementación de (a diferencia de Windows).

Tenga en cuenta que los administradores de ventanas pueden tener otros portapapeles, y por ejemplo el paquete RGtk2 tiene interfaces para portapapeles gtk.

Respuesta

12

No estoy seguro si este es el mejor manera, pero aquí es cómo podría conseguir que funcione:

  1. Instalar xclip: sudo apt-get install xclip
  2. leer el manual: man xclip
  3. Escribir al X11 primaria en R: write.table(1:10, pipe("xclip -i", "w"))

Actualización:

Tenga en cuenta que el objeto pasado a write.table no estará presente en el portapapeles hasta que el tubo está cerrado. Puede forzar el cierre de la tubería llamando al gc(). Por ejemplo:

write.table(1:10, pipe("xclip -i", "w")) # data may not be in clipboard 
gc()          # data written to primary clipboard 

Una mejor manera de administrar la conexión es utilizar una función con on.exit(close(con)), que cerrará el tubo incluso si la llamada write.table genera un error. Tenga en cuenta que debe asegurarse de escribir en el portapapeles que tiene la intención de usar (el principal es el predeterminado), según la configuración de su sistema.

write.xclip <- function(x, selection=c("primary", "secondary", "clipboard"), ...) { 
    if (!isTRUE(file.exists(Sys.which("xclip")[1L]))) 
    stop("Cannot find xclip") 
    selection <- match.arg(selection)[1L] 
    con <- pipe(paste0("xclip -i -selection ", selection), "w") 
    on.exit(close(con)) 
    write.table(x, con, ...) 
} 
+0

+1 Thanks. Lo aprecio. Todavía estoy interesado en ver qué otras estrategias existen. La razón principal por la que ocasionalmente me gusta pegar en el portapapeles es guardar un par de segundos, en lugar de escribir en un archivo y copiar desde el archivo. La estrategia anterior parece suponer que puedo predecir con anticipación que necesitaría el portapapeles. Tampoco pude hacerlo funcionar en R Studio. Solo pude hacerlo funcionar con la consola. –

+0

@JeromyAnglim También noté que se trataba de un problema de RStudio, por lo que es mejor que informe a los desarrolladores de RStudio. No sé lo que hicieron con el portapapeles. –

+1

Esto no funcionó para mí en ubuntu, ni en R Studio ni en la versión terminal de R. Admitiré que no leí completamente el hombre para xclip (paso 2), pero no creo que debería afectar los resultados. – geneorama

16
clipboard <- function(x, sep="\t", row.names=FALSE, col.names=TRUE){ 
    con <- pipe("xclip -selection clipboard -i", open="w") 
    write.table(x, con, sep=sep, row.names=row.names, col.names=col.names) 
    close(con) 
} 

vec <- c(1,2,3,4) 

clipboard(vec) 
clipboard(vec, ",", col.names=FALSE) 
clipboard(vec, " ", row.names=TRUE) 

Puede pegar de vuelta cualquier cosa que escribir en el portapapeles después de crear la función como tal. La pestaña de devoluciones predetermina los valores separados con la columna pero sin nombres de fila. Especifique otros separadores, incluya nombres de fila o excluya los nombres de columna a su gusto, como se muestra.

Editar: Para aclarar, aún necesita instalar xclip. Sin embargo, no es necesario que lo inicies por separado primero.

+0

Ninguna de estas soluciones funciona para mí :-( –

0

Versiones:

  • menta 18,1, canela
  • xclip 0,12
  • R 3.4.0 (2017-04-21)

no podría obtener las otras soluciones para trabajar , entonces yo man ed up. Este enfoque funciona para mí (basado en las soluciones de los demás).

write_clipboard = function(x, .rownames = F) { 
    #decide how to write 
    #windows is easy! 
    if (Sys.info()['sysname'] %in% c("Windows")) { 
     #just write as normal 
     write.table(x, "clipboard", sep = "\t", na = "", row.names = F) 
    } else { 
     #for non-windows, try xclip approach 
     #https://stackoverflow.com/a/10960498/3980197 
     write.xclip = function(x) { 
     #if xclip not installed 
     if (!isTRUE(file.exists(Sys.which("xclip")[1L]))) { 
      stop("Cannot find xclip") 
     } 
     con <- pipe("xclip -selection c", "w") 
     on.exit(close(con)) 
     write.table(x, con, sep = "\t", na = "", row.names = F) 
     } 

     tryCatch({ 
     write.xclip(x) 
     }, error = function(e) { 
     message("Could not write using xclip") 
     }) 
    } 
} 

Es una versión diluida de una función en my personal R package.

Lectura desde el portapapeles

La lectura es igualmente difícil. Aquí hay una función complementaria para lo anterior.

read_clipboard = function(header = T, 
          sep = "\t", 
          na.strings = c("", "NA"), 
          check.names = T, 
          stringsAsFactors = F, 
          dec = ".", 
          ...) { 
    #decide how to read 
    #windows is easy! 
    if (Sys.info()['sysname'] %in% c("Windows")) { 
    #just read as normal 
    read.table(file = con, sep = sep, header = header, check.names = check.names, na.strings = na.strings, stringsAsFactors = stringsAsFactors, dec = dec, ...) 
    } else { 
    #for non-windows, try xclip approach 
    #https://stackoverflow.com/a/10960498/3980197 
    read.xclip = function(x) { 
     #if xclip not installed 
     if (!isTRUE(file.exists(Sys.which("xclip")[1L]))) { 
     stop("Cannot find xclip") 
     } 
     con <- pipe("xclip -o -selection c", "r") 
     on.exit(close(con)) 
     read.table(file = con, sep = sep, header = header, check.names = check.names, na.strings = na.strings, stringsAsFactors = stringsAsFactors, dec = dec, ...) 
    } 

    tryCatch({ 
     read.xclip(x) 
    }, error = function(e) { 
     message(sprintf("error: %s", e$message)) 
    }) 
    } 
} 
Cuestiones relacionadas