Menu

Вывод и ввод в R (print, cat, readline)

Как устроен вывод в R — автопечать, print() против cat(), message() — и как читать пользовательский ввод через readline() и readLines().

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Как работает печать в R

У R есть привычка, которой нет ни у одного другого мейнстримного языка: в консоли инструкция печати вообще не нужна. Наберите имя переменной, нажмите Enter — и R напечатает её значение. Это автопечать, и именно поэтому учебники по R полны голых выражений.

Но у автопечати есть строгая граница: она срабатывает только для выражений на верхнем уровне. Внутри цикла for или тела функции голое значение вычисляется и молча выбрасывается:

Одинокое x печатается (оно на верхнем уровне), первый цикл не печатает ничего, а второй печатает 1, 2, 3, потому что просит об этом явно. «Мой цикл выполняется, но ничего не показывает» — один из самых частых вопросов по R, и вот весь ответ: внутри циклов и функций печать всегда ваша забота. (То же самое касается запуска скрипта через Rscript — то, что работало построчно в консоли, может замолчать внутри цикла.)

print() показывает значение так, как его видит R, — что делает её правильным инструментом для осмотра данных и неправильным для аккуратного вывода:

Бросаются в глаза две вещи. Строки сохраняют кавычкиprint() показывает точное представление, и кавычки говорят вам, что это символьное значение. И каждая строка начинается с числа в квадратных скобках вроде [1]: это индекс первого элемента в этой строке, так что когда длинный вектор переносится на новые строки, скобка каждой строки говорит, с какого элемента она продолжается. Это подсказка для чтения векторов, а не шум.

Если нужен вывод в стиле print(), но без кавычек, подойдут и print(x, quote = FALSE), и noquote(x), — но обычно в этот момент вам на самом деле нужен cat().

cat(): вывод для людей

cat() (concatenate-and-print) пишет сырой текст: без кавычек, без префиксов-индексов, аргументы соединяются пробелами. Плата за такой контроль — ничего не добавляется за вас, включая перевод строки:

Забыть "\n" — всеобщий обряд посвящения в cat(): без него следующий кусок вывода приклеится к той же строке. Доведите завершение вызовов cat() символом "\n" до рефлекса.

Разница в кавычках между двумя функциями на самом деле — разница в том, что они показывают. print() отображает управляющие последовательности так, как вы их набрали; cat() их отрисовывает:

print() показывает \t и \n буквально внутри кавычек — полезно, когда вы отлаживаете, что именно содержит строка. cat() превращает их в настоящую табуляцию и настоящий перенос строки — полезно, когда вы формируете вывод. Выбирайте по намерению: print() — осмотреть, cat() — показать.

Форматированные отчёты: sprintf() + cat()

Разделённых пробелами аргументов cat() хватает не на всё. Для выровненного форматированного вывода — фиксированные дроби, дополненные счётчики — соберите строку через sprintf() и передайте её в cat():

%-8s дополняет каждое имя до 8 символов, а %6.2f даёт каждому баллу одинаковую ширину и два знака после запятой, поэтому столбцы выравниваются. Эта пара — рабочая лошадка базового R для сообщений о прогрессе и небольших текстовых отчётов (форматные коды разобраны в статье про строки).

message() и warning(): другой канал

cat() и print() пишут в стандартный вывод — поток, в котором лежат результаты вашей программы. message() и warning() пишут в стандартный поток ошибок, предназначенный для комментариев о ходе выполнения:

На экране оба выглядят похоже, но разделение становится важным в момент перенаправления вывода: направьте stdout скрипта в файл — и 42 попадёт в файл, а служебная заметка останется в терминале. Это и есть правило большого пальца: результаты в stdout через cat(), комментарии в stderr через message(). Поэтому же message() (а не cat()) — вежливый способ для функций и пакетов разговаривать с пользователями: вызывающий может заглушить их через suppressMessages(), не потеряв настоящий вывод.

warning() сильнее — «что-то не так, но я продолжил», — и когда скрипт выполняется под Rscript, предупреждения собираются и показываются вместе в конце, а не по ходу дела (о том, как их читать, см. статью про отладку ошибок).

Чтение пользовательского ввода: readline() и readLines()

Чтобы задать пользователю вопрос в интерактивной сессии (консоль R или RStudio), используйте readline(). Эти примеры нельзя запустить во встроенном редакторе — у него нет панели ввода, — так что попробуйте их в локальной консоли:

# Interactive sessions only:
name <- readline("What is your name? ")
cat("Hello,", name, "\n")

age <- as.numeric(readline("Your age? "))
cat("Next year you'll be", age + 1, "\n")

Две вещи, которые нужно помнить. readline() всегда возвращает строку — преобразуйте через as.numeric(), прежде чем считать, и проверьте результат на NA на случай, если пользователь ввёл не число. А в неинтерактивном скрипте readline() вообще не ждёт ввода; она мгновенно возвращает "".

Для скрипта, запускаемого через Rscript, который должен читать переданный по конвейеру или набранный ввод, читайте из стандартного ввода:

# In a script run as: echo "Ada" | Rscript greet.R
line <- readLines(con = "stdin", n = 1)
cat("Hello,", line, "\n")

readLines(con = "stdin") без n читает все строки до конца ввода — стандартная форма для скриптов-фильтров. Чтение файлов с данными — другая задача, и для неё есть инструменты получше; начните с read-csv, когда вашим входом является набор данных, а не клавиатура.

Что вы уносите с собой

  • Автопечать происходит только на верхнем уровне — внутри циклов и функций вызывайте print() или cat() сами.
  • print() осматривает: кавычки у строк, префиксы-индексы [1], экранирование показывается буквально.
  • cat() представляет: сырой текст, аргументы через пробелы, а "\n" добавляете вы.
  • sprintf() + cat() — паттерн базового R для форматированного выровненного вывода.
  • Результаты идут в stdout (cat), комментарии — в stderr (message, warning).
  • readline() — для интерактивного ввода (всегда строка!); readLines(con = "stdin") — для Rscript.

Дальше: операторы — арифметические, сравнения и логические, которые управляют каждым написанным вами условием.

Часто задаваемые вопросы

В чём разница между print() и cat() в R?

print() показывает значение так, как его представляет R: строки сохраняют кавычки, а каждая строка вывода получает префикс вида [1]. cat() пишет сырой текст без кавычек, без индексов и без автоматического переноса строки ("\n" вы добавляете сами). Используйте print() для осмотра объектов и cat() для вывода, предназначенного людям.

Почему мой цикл в R ничего не печатает?

Автопечать работает только для выражений на верхнем уровне. Внутри цикла for или тела функции голое x вычисляется и молча отбрасывается. Оберните явно: print(x) или cat(x, "\n").

Как прочитать пользовательский ввод в R?

В интерактивной сессии readline("prompt: ") читает одну введённую строку как текст (преобразуйте через as.numeric(), если нужно число). В скрипте, запущенном через Rscript, readline() не ждёт ввода — читайте из стандартного ввода через readLines(con = "stdin", n = 1).

Как напечатать без кавычек в R?

Используйте cat("hello\n") — она никогда не добавляет кавычки. Если нужна именно семантика print(), но без кавычек, подойдут print("hello", quote = FALSE) или noquote("hello").

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ