REPL
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
Código fuente: lib/repl.js
El módulo node:repl
proporciona una implementación de Read-Eval-Print-Loop (REPL) que está disponible tanto como un programa independiente como para ser incluido en otras aplicaciones. Se puede acceder a él usando:
import repl from 'node:repl'
const repl = require('node:repl')
Diseño y características
El módulo node:repl
exporta la clase repl.REPLServer
. Mientras se ejecutan, las instancias de repl.REPLServer
aceptarán líneas individuales de entrada del usuario, las evaluarán de acuerdo con una función de evaluación definida por el usuario y luego emitirán el resultado. La entrada y la salida pueden ser de stdin
y stdout
, respectivamente, o pueden estar conectadas a cualquier stream de Node.js.
Las instancias de repl.REPLServer
admiten la finalización automática de entradas, la vista previa de la finalización, la edición de líneas simplista al estilo Emacs, las entradas de varias líneas, la búsqueda inversa al estilo ZSH, la búsqueda de historial basada en subcadenas al estilo ZSH, la salida con estilo ANSI, el guardado y la restauración del estado actual de la sesión REPL, la recuperación de errores y funciones de evaluación personalizables. Los terminales que no admiten estilos ANSI y la edición de líneas al estilo Emacs recurren automáticamente a un conjunto de funciones limitado.
Comandos y teclas especiales
Todas las instancias REPL admiten los siguientes comandos especiales:
.break
: Cuando se está en el proceso de ingresar una expresión de varias líneas, ingrese el comando.break
(o presione +) para cancelar la entrada o el procesamiento adicional de esa expresión..clear
: Restablece elcontext
del REPL a un objeto vacío y borra cualquier expresión de varias líneas que se esté ingresando..exit
: Cierra el flujo de E/S, lo que hace que el REPL se cierre..help
: Muestra esta lista de comandos especiales..save
: Guarda la sesión REPL actual en un archivo:\> .save ./archivo/para/guardar.js
.load
: Carga un archivo en la sesión REPL actual.\> .load ./archivo/para/cargar.js
.editor
: Ingresa al modo editor (+ para finalizar, + para cancelar).
> .editor
// Ingresando al modo editor (^D para finalizar, ^C para cancelar)
function welcome(name) {
return `¡Hola ${name}!`;
}
welcome('Usuario de Node.js');
// ^D
'¡Hola Usuario de Node.js!'
>
Las siguientes combinaciones de teclas en el REPL tienen estos efectos especiales:
- +: Cuando se presiona una vez, tiene el mismo efecto que el comando
.break
. Cuando se presiona dos veces en una línea en blanco, tiene el mismo efecto que el comando.exit
. - +: Tiene el mismo efecto que el comando
.exit
. - : Cuando se presiona en una línea en blanco, muestra las variables globales y locales (alcance). Cuando se presiona mientras se ingresa otra entrada, muestra las opciones de autocompletado relevantes.
Para las combinaciones de teclas relacionadas con la búsqueda inversa, consulte reverse-i-search
. Para todas las demás combinaciones de teclas, consulte Combinaciones de teclas TTY.
Evaluación predeterminada
De forma predeterminada, todas las instancias de repl.REPLServer
utilizan una función de evaluación que evalúa expresiones de JavaScript y proporciona acceso a los módulos integrados de Node.js. Este comportamiento predeterminado se puede anular pasando una función de evaluación alternativa cuando se crea la instancia de repl.REPLServer
.
Expresiones de JavaScript
El evaluador predeterminado admite la evaluación directa de expresiones de JavaScript:
> 1 + 1
2
> const m = 2
undefined
> m + 1
3
A menos que se definan dentro de bloques o funciones, las variables declaradas implícitamente o utilizando las palabras clave const
, let
o var
se declaran en el ámbito global.
Ámbito global y local
El evaluador predeterminado proporciona acceso a cualquier variable que exista en el ámbito global. Es posible exponer una variable al REPL explícitamente asignándola al objeto context
asociado a cada REPLServer
:
import repl from 'node:repl'
const msg = 'message'
repl.start('> ').context.m = msg
const repl = require('node:repl')
const msg = 'message'
repl.start('> ').context.m = msg
Las propiedades en el objeto context
aparecen como locales dentro del REPL:
$ node repl_test.js
> m
'message'
Las propiedades de contexto no son de solo lectura de forma predeterminada. Para especificar globales de solo lectura, las propiedades de contexto deben definirse utilizando Object.defineProperty()
:
import repl from 'node:repl'
const msg = 'message'
const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
})
const repl = require('node:repl')
const msg = 'message'
const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
})
Acceso a módulos centrales de Node.js
El evaluador predeterminado cargará automáticamente los módulos centrales de Node.js en el entorno REPL cuando se utilicen. Por ejemplo, a menos que se declare como una variable global o con ámbito, la entrada fs
se evaluará bajo demanda como global.fs = require('node:fs')
.
> fs.createReadStream('./some/file');
Excepciones globales no capturadas
[Historial]
Versión | Cambios |
---|---|
v12.3.0 | El evento 'uncaughtException' se activa a partir de ahora si el REPL se usa como un programa independiente. |
El REPL usa el módulo domain
para capturar todas las excepciones no capturadas para esa sesión de REPL.
Este uso del módulo domain
en el REPL tiene estos efectos secundarios:
- Las excepciones no capturadas solo emiten el evento
'uncaughtException'
en el REPL independiente. Agregar un detector para este evento en un REPL dentro de otro programa Node.js resulta enERR_INVALID_REPL_INPUT
. - Intentar usar
process.setUncaughtExceptionCaptureCallback()
lanza un errorERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE
.
Asignación de la variable _
(guion bajo)
[Historial]
Versión | Cambios |
---|---|
v9.8.0 | Se agregó soporte para _error . |
El evaluador predeterminado, por defecto, asignará el resultado de la expresión evaluada más recientemente a la variable especial _
(guion bajo). Establecer explícitamente _
a un valor deshabilitará este comportamiento.
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Asignación de expresión a _ ahora deshabilitada.
4
> 1 + 1
2
> _
4
De manera similar, _error
se referirá al último error visto, si hubo alguno. Establecer explícitamente _error
a un valor deshabilitará este comportamiento.
> throw new Error('foo');
Uncaught Error: foo
> _error.message
'foo'
Palabra clave await
El soporte para la palabra clave await
está habilitado en el nivel superior.
> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Uncaught Error: REPL await
at REPL2:1:54
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined
Una limitación conocida del uso de la palabra clave await
en el REPL es que invalidará el alcance léxico de las palabras clave const
y let
.
Por ejemplo:
> const m = await Promise.resolve(123)
undefined
> m
123
> const m = await Promise.resolve(234)
undefined
> m
234
--no-experimental-repl-await
deberá deshabilitar el await de nivel superior en REPL.
Búsqueda inversa incremental
Añadido en: v13.6.0, v12.17.0
El REPL admite la búsqueda inversa incremental bidireccional similar a ZSH. Se activa con + para buscar hacia atrás y + para buscar hacia adelante.
Se omitirán las entradas duplicadas del historial.
Las entradas se aceptan tan pronto como se presiona cualquier tecla que no se corresponda con la búsqueda inversa. La cancelación es posible presionando o +.
Cambiar la dirección busca inmediatamente la siguiente entrada en la dirección esperada desde la posición actual.
Funciones de evaluación personalizadas
Cuando se crea un nuevo repl.REPLServer
, se puede proporcionar una función de evaluación personalizada. Esto se puede usar, por ejemplo, para implementar aplicaciones REPL totalmente personalizadas.
Lo siguiente ilustra un ejemplo de un REPL que eleva al cuadrado un número dado:
import repl from 'node:repl'
function byThePowerOfTwo(number) {
return number * number
}
function myEval(cmd, context, filename, callback) {
callback(null, byThePowerOfTwo(cmd))
}
repl.start({ prompt: 'Introduce un número: ', eval: myEval })
const repl = require('node:repl')
function byThePowerOfTwo(number) {
return number * number
}
function myEval(cmd, context, filename, callback) {
callback(null, byThePowerOfTwo(cmd))
}
repl.start({ prompt: 'Introduce un número: ', eval: myEval })
Errores recuperables
En el prompt de REPL, al presionar se envía la línea de entrada actual a la función eval
. Para admitir la entrada de varias líneas, la función eval
puede devolver una instancia de repl.Recoverable
a la función de devolución de llamada proporcionada:
function myEval(cmd, context, filename, callback) {
let result
try {
result = vm.runInThisContext(cmd)
} catch (e) {
if (isRecoverableError(e)) {
return callback(new repl.Recoverable(e))
}
}
callback(null, result)
}
function isRecoverableError(error) {
if (error.name === 'SyntaxError') {
return /^(Unexpected end of input|Unexpected token)/.test(error.message)
}
return false
}
Personalización de la salida de REPL
De forma predeterminada, las instancias de repl.REPLServer
formatean la salida utilizando el método util.inspect()
antes de escribir la salida en el flujo Writable
proporcionado (process.stdout
de forma predeterminada). La opción de inspección showProxy
se establece en true de forma predeterminada y la opción colors
se establece en true dependiendo de la opción useColors
de REPL.
La opción booleana useColors
se puede especificar durante la construcción para indicar al escritor predeterminado que utilice códigos de estilo ANSI para colorear la salida del método util.inspect()
.
Si el REPL se ejecuta como un programa independiente, también es posible cambiar los valores predeterminados de inspección de REPL desde dentro del REPL utilizando la propiedad inspect.replDefaults
que refleja el defaultOptions
de util.inspect()
.
> util.inspect.replDefaults.compact = false;
false
> [1]
[
1
]
>
Para personalizar completamente la salida de una instancia repl.REPLServer
pasa una nueva función para la opción writer
en la construcción. El siguiente ejemplo, por ejemplo, simplemente convierte cualquier texto de entrada a mayúsculas:
import repl from 'node:repl'
const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter })
function myEval(cmd, context, filename, callback) {
callback(null, cmd)
}
function myWriter(output) {
return output.toUpperCase()
}
const repl = require('node:repl')
const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter })
function myEval(cmd, context, filename, callback) {
callback(null, cmd)
}
function myWriter(output) {
return output.toUpperCase()
}
Clase: REPLServer
Agregado en: v0.1.91
options
<Objeto> | <cadena> Consulterepl.start()
- Extiende: <readline.Interface>
Las instancias de repl.REPLServer
se crean usando el método repl.start()
o directamente usando la palabra clave new
de JavaScript.
import repl from 'node:repl'
const options = { useColors: true }
const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
const repl = require('node:repl')
const options = { useColors: true }
const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
Evento: 'exit'
Agregado en: v0.7.7
El evento 'exit'
se emite cuando se sale del REPL, ya sea recibiendo el comando .exit
como entrada, presionando + dos veces para señalar SIGINT
, o presionando + para señalar 'end'
en el flujo de entrada. La función de devolución de llamada del oyente se invoca sin ningún argumento.
replServer.on('exit', () => {
console.log('¡Recibido evento "exit" de repl!')
process.exit()
})
Evento: 'reset'
Agregado en: v0.11.0
El evento 'reset'
se emite cuando se restablece el contexto del REPL. Esto ocurre cada vez que se recibe el comando .clear
como entrada a menos que el REPL esté utilizando el evaluador predeterminado y la instancia repl.REPLServer
se haya creado con la opción useGlobal
establecida en true
. La función de devolución de llamada del receptor se llamará con una referencia al objeto context
como único argumento.
Esto se puede usar principalmente para reinicializar el contexto de REPL a algún estado predefinido:
import repl from 'node:repl'
function initializeContext(context) {
context.m = 'test'
}
const r = repl.start({ prompt: '> ' })
initializeContext(r.context)
r.on('reset', initializeContext)
const repl = require('node:repl')
function initializeContext(context) {
context.m = 'test'
}
const r = repl.start({ prompt: '> ' })
initializeContext(r.context)
r.on('reset', initializeContext)
Cuando se ejecuta este código, la variable global 'm'
se puede modificar pero luego se restablece a su valor inicial utilizando el comando .clear
:
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Clearing context...
> m
'test'
>
replServer.defineCommand(keyword, cmd)
Agregado en: v0.3.0
keyword
<string> La palabra clave del comando (sin un carácter.
inicial).cmd
<Object> | <Function> La función a invocar cuando se procesa el comando.
El método replServer.defineCommand()
se utiliza para agregar nuevos comandos con prefijo .
a la instancia REPL. Dichos comandos se invocan escribiendo un .
seguido de la keyword
. El cmd
es una Function
o un Object
con las siguientes propiedades:
help
<string> Texto de ayuda que se mostrará cuando se ingrese.help
(Opcional).action
<Function> La función a ejecutar, que opcionalmente acepta un solo argumento de cadena.
El siguiente ejemplo muestra dos nuevos comandos agregados a la instancia REPL:
import repl from 'node:repl'
const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
help: 'Say hello',
action(name) {
this.clearBufferedCommand()
console.log(`Hello, ${name}!`)
this.displayPrompt()
},
})
replServer.defineCommand('saybye', function saybye() {
console.log('Goodbye!')
this.close()
})
const repl = require('node:repl')
const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
help: 'Say hello',
action(name) {
this.clearBufferedCommand()
console.log(`Hello, ${name}!`)
this.displayPrompt()
},
})
replServer.defineCommand('saybye', function saybye() {
console.log('Goodbye!')
this.close()
})
Los nuevos comandos se pueden usar desde dentro de la instancia REPL:
> .sayhello Node.js User
Hello, Node.js User!
> .saybye
Goodbye!
replServer.displayPrompt([preserveCursor])
Agregado en: v0.1.91
preserveCursor
<boolean>
El método replServer.displayPrompt()
prepara la instancia REPL para la entrada del usuario, imprimiendo el prompt
configurado en una nueva línea en la salida
y reanudando la entrada
para aceptar una nueva entrada.
Cuando se introduce una entrada de varias líneas, se imprime una elipsis en lugar del 'prompt'.
Cuando preserveCursor
es true
, la posición del cursor no se restablecerá a 0
.
El método replServer.displayPrompt
está destinado principalmente a ser llamado desde la función de acción para los comandos registrados utilizando el método replServer.defineCommand()
.
replServer.clearBufferedCommand()
Agregado en: v9.0.0
El método replServer.clearBufferedCommand()
borra cualquier comando que haya sido almacenado en búfer pero que aún no se haya ejecutado. Este método está destinado principalmente a ser llamado desde la función de acción para los comandos registrados utilizando el método replServer.defineCommand()
.
replServer.setupHistory(historyPath, callback)
Agregado en: v11.10.0
historyPath
<string> la ruta al archivo de historialcallback
<Function> llamada cuando las escrituras del historial están listas o en caso de errorerr
<Error>repl
<repl.REPLServer>
Inicializa un archivo de registro del historial para la instancia REPL. Al ejecutar el binario de Node.js y usar el REPL de la línea de comandos, se inicializa un archivo de historial de forma predeterminada. Sin embargo, este no es el caso al crear un REPL mediante programación. Use este método para inicializar un archivo de registro del historial cuando trabaje con instancias REPL mediante programación.
repl.builtinModules
Agregado en: v14.5.0
Una lista de los nombres de todos los módulos de Node.js, p. ej., 'http'
.
repl.start([options])
[Historial]
Versión | Cambios |
---|---|
v13.4.0, v12.17.0 | La opción preview ahora está disponible. |
v12.0.0 | La opción terminal ahora sigue la descripción predeterminada en todos los casos y useColors verifica hasColors() si está disponible. |
v10.0.0 | Se eliminó el replMode REPL_MAGIC_MODE . |
v6.3.0 | Ahora se admite la opción breakEvalOnSigint . |
v5.8.0 | El parámetro options ahora es opcional. |
v0.1.91 | Agregado en: v0.1.91 |
prompt
<cadena> El prompt de entrada a mostrar. Predeterminado:'\> '
(con un espacio al final).input
<stream.Readable> El flujoReadable
desde el cual se leerá la entrada REPL. Predeterminado:process.stdin
.output
<stream.Writable> El flujoWritable
al que se escribirá la salida REPL. Predeterminado:process.stdout
.terminal
<boolean> Si estrue
, especifica que laoutput
debe tratarse como una terminal TTY. Predeterminado: verificar el valor de la propiedadisTTY
en el flujooutput
al instanciar.eval
<Función> La función que se usará al evaluar cada línea de entrada dada. Predeterminado: un envoltorio asíncrono para la función JavaScripteval()
. Una funcióneval
puede generar un error conrepl.Recoverable
para indicar que la entrada estaba incompleta y solicitar líneas adicionales.useColors
<boolean> Si estrue
, especifica que la funciónwriter
predeterminada debe incluir estilos de color ANSI en la salida REPL. Si se proporciona una funciónwriter
personalizada, esto no tiene efecto. Predeterminado: verificar la compatibilidad de color en el flujooutput
si el valorterminal
de la instancia REPL estrue
.useGlobal
<boolean> Si estrue
, especifica que la función de evaluación predeterminada usará el JavaScriptglobal
como contexto en lugar de crear un nuevo contexto separado para la instancia REPL. El REPL de la CLI de Node establece este valor entrue
. Predeterminado:false
.ignoreUndefined
<boolean> Si estrue
, especifica que el escritor predeterminado no mostrará el valor de retorno de un comando si se evalúa comoundefined
. Predeterminado:false
.writer
<Función> La función que se invocará para formatear la salida de cada comando antes de escribir enoutput
. Predeterminado:util.inspect()
.completer
<Función> Una función opcional utilizada para la auto-finalización personalizada de la tecla Tab. Consultereadline.InterfaceCompleter
para ver un ejemplo.replMode
<symbol> Una bandera que especifica si el evaluador predeterminado ejecuta todos los comandos de JavaScript en modo estricto o en modo predeterminado (flexible). Los valores aceptables son:repl.REPL_MODE_SLOPPY
para evaluar expresiones en modo flexible.repl.REPL_MODE_STRICT
para evaluar expresiones en modo estricto. Esto es equivalente a anteponer cada declaración de repl con'use strict'
.
breakEvalOnSigint
<boolean> Detener la evaluación del fragmento de código actual cuando se recibeSIGINT
, como cuando se presiona +. Esto no se puede usar junto con una funcióneval
personalizada. Predeterminado:false
.preview
<boolean> Define si el repl imprime auto-completado y previsualizaciones de salida o no. Predeterminado:true
con la función eval predeterminada yfalse
en caso de que se utilice una función eval personalizada. Siterminal
es falso, entonces no hay vistas previas y el valor depreview
no tiene efecto.
Devuelve: <repl.REPLServer>
El método repl.start()
crea e inicia una instancia de repl.REPLServer
.
Si options
es una cadena, entonces especifica el prompt de entrada:
import repl from 'node:repl'
// un prompt estilo Unix
repl.start('$ ')
const repl = require('node:repl')
// un prompt estilo Unix
repl.start('$ ')
El REPL de Node.js
Node.js utiliza el módulo node:repl
para proporcionar su propia interfaz interactiva para ejecutar JavaScript. Esto se puede utilizar ejecutando el binario de Node.js sin pasar ningún argumento (o pasando el argumento -i
):
$ node
> const a = [1, 2, 3];
undefined
> a
[ 1, 2, 3 ]
> a.forEach((v) => {
... console.log(v);
... });
1
2
3
Opciones de variables de entorno
Varios comportamientos del REPL de Node.js se pueden personalizar utilizando las siguientes variables de entorno:
NODE_REPL_HISTORY
: Cuando se proporciona una ruta válida, el historial persistente del REPL se guardará en el archivo especificado en lugar de.node_repl_history
en el directorio de inicio del usuario. Establecer este valor a''
(una cadena vacía) deshabilitará el historial persistente del REPL. Los espacios en blanco se eliminarán del valor. En las plataformas Windows, las variables de entorno con valores vacíos no son válidas, así que establezca esta variable en uno o más espacios para deshabilitar el historial persistente del REPL.NODE_REPL_HISTORY_SIZE
: Controla cuántas líneas de historial se conservarán si el historial está disponible. Debe ser un número positivo. Predeterminado:1000
.NODE_REPL_MODE
: Puede ser'sloppy'
o'strict'
. Predeterminado:'sloppy'
, que permitirá que se ejecute código en modo no estricto.
Historial persistente
De forma predeterminada, el REPL de Node.js conservará el historial entre sesiones REPL de node
guardando las entradas en un archivo .node_repl_history
ubicado en el directorio de inicio del usuario. Esto se puede deshabilitar configurando la variable de entorno NODE_REPL_HISTORY=''
.
Uso del REPL de Node.js con editores de línea avanzados
Para editores de línea avanzados, inicie Node.js con la variable de entorno NODE_NO_READLINE=1
. Esto iniciará el REPL principal y el depurador en la configuración de terminal canónica, lo que permitirá el uso con rlwrap
.
Por ejemplo, lo siguiente se puede agregar a un archivo .bashrc
:
alias node="env NODE_NO_READLINE=1 rlwrap node"
Iniciar múltiples instancias REPL contra una única instancia en ejecución
Es posible crear y ejecutar múltiples instancias REPL contra una única instancia en ejecución de Node.js que compartan un único objeto global
pero tengan interfaces de E/S separadas.
El siguiente ejemplo, por ejemplo, proporciona REPL separados en stdin
, un socket Unix y un socket TCP:
import net from 'node:net'
import repl from 'node:repl'
import process from 'node:process'
let connections = 0
repl.start({
prompt: 'Node.js a través de stdin> ',
input: process.stdin,
output: process.stdout,
})
net
.createServer(socket => {
connections += 1
repl
.start({
prompt: 'Node.js a través de socket Unix> ',
input: socket,
output: socket,
})
.on('exit', () => {
socket.end()
})
})
.listen('/tmp/node-repl-sock')
net
.createServer(socket => {
connections += 1
repl
.start({
prompt: 'Node.js a través de socket TCP> ',
input: socket,
output: socket,
})
.on('exit', () => {
socket.end()
})
})
.listen(5001)
const net = require('node:net')
const repl = require('node:repl')
let connections = 0
repl.start({
prompt: 'Node.js a través de stdin> ',
input: process.stdin,
output: process.stdout,
})
net
.createServer(socket => {
connections += 1
repl
.start({
prompt: 'Node.js a través de socket Unix> ',
input: socket,
output: socket,
})
.on('exit', () => {
socket.end()
})
})
.listen('/tmp/node-repl-sock')
net
.createServer(socket => {
connections += 1
repl
.start({
prompt: 'Node.js a través de socket TCP> ',
input: socket,
output: socket,
})
.on('exit', () => {
socket.end()
})
})
.listen(5001)
Al ejecutar esta aplicación desde la línea de comandos, se iniciará un REPL en stdin. Otros clientes REPL pueden conectarse a través del socket Unix o el socket TCP. telnet
, por ejemplo, es útil para conectarse a sockets TCP, mientras que socat
se puede utilizar para conectarse tanto a sockets Unix como TCP.
Al iniciar un REPL desde un servidor basado en socket Unix en lugar de stdin, es posible conectarse a un proceso Node.js de larga duración sin reiniciarlo.
Para un ejemplo de cómo ejecutar un REPL "completo" (terminal
) a través de una instancia de net.Server
y net.Socket
, consulte: https://gist.github.com/TooTallNate/2209310.
Para un ejemplo de cómo ejecutar una instancia REPL a través de curl(1)
, consulte: https://gist.github.com/TooTallNate/2053342.
Este ejemplo tiene fines puramente educativos para demostrar cómo se pueden iniciar los REPL de Node.js utilizando diferentes flujos de E/S. No se debe utilizar en entornos de producción ni en ningún contexto donde la seguridad sea una preocupación sin medidas de protección adicionales. Si necesita implementar REPL en una aplicación del mundo real, considere enfoques alternativos que mitiguen estos riesgos, como el uso de mecanismos de entrada seguros y evitar interfaces de red abiertas.