Вопрос по r – Как написать в буфер обмена на Ubuntu / Linux в R?

28

Я использую Ubuntu 11.10, и я хотел бы иметь возможность записи в буфер обмена (или основной выбор). Следующее дает ошибку

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

How can I write to the clipboard/primary selection?

Обратите внимание, что я виделэтот старый пост R-Help, но я до сих пор не понимаю, что мне делать.

Linux does not have a clipboard but an X11 session has primary and secondary selections. ?file says

Clipboard:

  '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")'.

so RTFM applied. Writing to an X11 selection needs multiple threads and I did not think it worth the very considerable effort of implementing (unlike for Windows).

Note that window managers may have other clipboards, and for example the RGtk2 package has interfaces to gtk clipboards.

Ваш Ответ

4   ответа
1

Mint 18.1, Cinnamon xclip 0.12 R 3.4.0 (2017-04-21)

Я не мог заставить другие решения работать, поэтому яmanизд. Этот подход работает для меня (на основе других решений).

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")
      })
    }
}

Это расширенная версия функции вмой личный пакет R.

Reading from the clipboard

Чтение одинаково сложно. Здесь сопутствующая функция для вышеупомянутого.

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))
    })
  }
}
18
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)

что вы пишете в буфер обмена после создания функции как таковой. По умолчанию возвращает разделенные табуляцией значения со столбцом, но без имен строк. Укажите другие разделители, включите имена строк или исключите имена столбцов по своему вкусу, как показано.

Изменить: чтобы уточнить, вам все еще нужно установить xclip. Однако вам не нужно сначала запускать его отдельно.

Ни одно из этих решений не работает для меня :-(
1

x <- 1:10
clipr::write_clip(x)
13

best Кстати, но вот как я мог заставить его работать:

Install xclip: sudo apt-get install xclip Read the manual: man xclip Write to X11 primary in R: write.table(1:10, pipe("xclip -i", "w"))

Update:

Обратите внимание, что объект переданwrite.table не будет присутствовать в буфере обмена, пока труба не будет закрыта. Вы можете заставить трубу закрыться, позвонивgc(), Например:

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

Лучший способ управлять соединением - использовать функцию сon.exit(close(con)), который закроет трубу, даже еслиwrite.table вызов выдает ошибку. Обратите внимание, что вам необходимо убедиться, что вы записываете в буфер обмена, который вы намереваетесь использовать (основной по умолчанию), в зависимости от настроек вашей системы.

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, ...)
}
@JeromyAnglim Я также заметил, что это проблема RStudio, поэтому вам лучше сообщить разработчикам RStudio. Я не знаю, что они сделали с буфером обмена.
+1 Спасибо. Я ценю его. Мне все еще интересно посмотреть, какие существуют другие стратегии. Основная причина, по которой мне иногда нравится вставлять в буфер обмена, - это сэкономить пару секунд вместо записи в файл и копирования из файла. Вышеупомянутая стратегия, кажется, предполагает, что я могу заранее предсказать, что мне понадобится буфер обмена. Я также не смог заставить его работать в R Studio. Я мог только заставить его работать с консолью. Jeromy Anglim
У меня тоже не сработало (Linux Mint 18, основан на Ubuntu 16.04).
@ KeithHughitt: выглядит так, потому что труба не очищается до тех пор, пока соединение не будет закрыто. Вы можете заставить его закрыться, позвонивgc(), но с помощью функции иon.exit является более надежным. Я обновил свой ответ соответственно.
Это не сработало для меня в Ubuntu, ни в R Studio, ни в терминальной версии R. Я признаю, что не полностью прочитал man для xclip (шаг 2), но я не думаю, что это должно повлиять на результаты.

Похожие вопросы