Este sitio tenía muchos problemas relacionados con la implementación de varios idiomas en la etiqueta de intérprete . Sin embargo, prácticamente todos ellos eran lenguajes esotéricos que nadie usa. Es hora de hacer un intérprete para un lenguaje práctico que la mayoría de los usuarios aquí probablemente ya conozcan. Sí, es un script de shell, en caso de que tenga problemas para leer el título (no es que tenga). (Sí, hice este desafío intencionalmente, ya que estoy aburrido de que lenguajes como GolfScript y Befunge ganen todo, así que pongo un desafío donde un lenguaje de programación más práctico tiene mayores posibilidades de ganar)
Sin embargo, el script de shell es un lenguaje relativamente grande, por lo que no le pediré que lo implemente. En cambio, voy a hacer un pequeño subconjunto de funcionalidad de script de shell.
El subconjunto que decidí es el siguiente:
- Ejecución de programas (sin embargo, los programas solo contendrán letras, incluso si se permiten comillas simples)
- Argumentos del programa
- Comillas simples (aceptando cualquier carácter ASCII imprimible, incluyendo espacios en blanco, excluyendo comillas simples)
- Cadenas sin comillas (que permiten letras, números y guiones ASCII)
- Tubería
- Declaraciones vacías
- Múltiples declaraciones separadas por una nueva línea.
- Espacios finales / iniciales / múltiples
En esta tarea, debe leer la entrada de STDIN y ejecutar cada comando solicitado. Puede asumir de forma segura un sistema operativo compatible con POSIX, por lo que no hay necesidad de portabilidad con Windows, ni nada de eso. Puede asumir con seguridad que los programas que no se canalizan a otros programas no leerán de STDIN. Puede asumir con seguridad que los comandos existirán. Puede asumir con seguridad que no se usará nada más. Si se rompe alguna suposición segura, puede hacer cualquier cosa. Puede suponer con seguridad a lo sumo 15 argumentos y líneas por debajo de 512 caracteres (si necesita una asignación de memoria explícita, o algo así, realmente voy a dar pequeñas posibilidades de ganar para C, incluso si todavía son pequeños). No tiene que limpiar los descriptores de archivo.
Se le permite ejecutar programas en cualquier momento, incluso después de recibir la línea completa o después de que STDIN finalice. Elija cualquier enfoque que desee.
Caso de prueba simple que le permite probar su shell (observe el espacio en blanco de seguimiento después del tercer comando):
echo hello world
printf '%08X\n' 1234567890
'echo' 'Hello, world!'
echo heeeeeeelllo | sed 's/\(.\)\1\+/\1/g'
yes|head -3
echo '\\'
echo 'foo bar baz' | sed 's/bar/BAR/' | sed 's/baz/zap/'
El programa anterior debería generar el siguiente resultado:
hello world
499602D2
Hello, world!
helo
y
y
y
\\
foo BAR zap
No se le permite ejecutar el shell en sí, a menos que no tenga ningún argumento para el comando (esta excepción se hizo para Perl, que ejecuta el comando en el shell cuando se coloca solo un argumento system
, pero no dude en abusar de esta excepción para otros idiomas también, si puede hacerlo de una manera que guarde caracteres), o el comando que ejecuta es el propio shell. Este es probablemente el mayor problema en este desafío, ya que muchos lenguajes tienen system
funciones que ejecutan shell. En su lugar, utilice las API de lenguaje que llaman a los programas directamente, como el subprocess
módulo en Python. De todos modos, esta es una buena idea para la seguridad, y bueno, no querrías crear un shell inseguro, ¿quieres? Lo más probable es que detenga PHP, pero de todos modos hay otros lenguajes para elegir.
Si usted va a hacer su programa en el script de shell, no está permitido el uso eval
, source
o .
(como en, una función, no un personaje). En mi opinión, el desafío sería demasiado fácil.
Se permite el abuso inteligente de las reglas. Hay muchas cosas que rechacé explícitamente, pero estoy casi seguro de que todavía puedes hacer cosas que no he pensado. A veces me sorprende cómo la gente interpreta mis reglas. Además, recuerda que puedes hacer cualquier cosa por lo que no he mencionado. Por ejemplo, si trato de usar variables, puede borrar el disco duro (pero no lo haga).
El código más corto gana, ya que este es codegolf.
fuente
Respuestas:
Bash (92 bytes)
Aprovechando la misma laguna como esta respuesta , aquí hay una solución mucho más corta:
Python (
247241239 bytes)fuente
*
), pero aparte de eso, se ve muy bien :-). Me sorprende que un nuevo miembro haya hecho una solución tan buena para un problema difícil.C (340 bytes)
No tengo ninguna experiencia en golf, pero tienes que comenzar en alguna parte, así que aquí va:
Agregué saltos de línea para que no tenga que desplazarse, pero no los incluí en mi recuento ya que no tienen significado semántico. Aquellos después de las directivas del preprocesador son obligatorios y se contaron.
Versión sin golf
Caracteristicas
'ec'ho He'll''o 'world
trabajar como deberían. Bien podría ser que el código hubiera sido más simple sin esta característica, por lo que agradeceré una aclaración si esto es necesario.Problemas conocidos
execvp
llamada falla, por ejemplo, debido a un nombre de programa mal escrito. Luego tenemos dos procesos jugando a ser shell simultáneamente.Caracteres especiales '|' y el salto de línea conservan su significado especial dentro de las cadenas citadas. Esto infringe los requisitos, por lo que estoy investigando formas de solucionarlo.Fijo, a un costo de aproximadamente 11 bytes.Otras notas
echo 'foo bar baz' | sed 's/bar/BAR/' | sed 's/baz/zap/'
colgó. Aparentemente, el problema era el tubo de escritura no cerrado, así que tuve que agregar ese comando de cierre, que aumentó el tamaño de mi código en 10 bytes. Quizás haya sistemas en los que no surja esta situación, por lo que mi código podría estar clasificado con 10 bytes menos. No lo sé.?:
puede haber anidado,
sin él(…)
.fuente
int c, m, f[3];
afueramain
, para evitar declarar tipos. Para las variables globales, no tiene que declararint
. Pero en general, una solución interesante.yes|head -3
salen dos veces y continúan para siempre y el shell se cierra después de cada comando. Estoy usando gcc versión 4.6.3 (Ubuntu / Linaro 4.6.3-1ubuntu5) sin ningún interruptor.#define B break;case
(elbreak;
anterior sedefault
convierte)B-1:
) y 2 reemplazandocase'\n'
andcase'\''
) concase 10
ycase 39
.bash (+ pantalla) 160
Producirá algo como:
fuente
Factor (208 caracteres)
Dado que las reglas no permiten descargar el trabajo a un tercero ( http://www.compileonline.com/execute_bash_online.php ), aquí hay una solución:
Puede escribir el programa como una línea aún más corta en la respuesta también ( 201 caracteres):
fuente
Perl, 135 caracteres.
Este caparazón hace algunas cosas estúpidas. Inicie un shell interactivo con
perl shell.pl
y pruébelo:ls
imprime en una columna, porque la salida estándar no es una terminal. El shell redirige la salida estándar a una tubería y lee la tubería.perl -E 'say "hi"; sleep 1'
espera 1 segundo para saludar, porque el shell retrasa la salida.dd
lee 0 bytes, a menos que sea el primer comando para este shell. El shell redirige la entrada estándar desde una tubería vacía, para cada tubería después de la primera.perl -e '$0 = screamer; print "A" x 1000000' | dd of=/dev/null
se completa con éxitoperl -e '$0 = screamer; print "A" x 1000000' | cat | dd of=/dev/null
cuelga la cáscara!pkill -f screamer
otro caparazón), entonces el caparazón se reanuda.perl -e 'fork and exit; $0 = sleeper; sleep'
cuelga la cáscara!'echo $((2+3))'
ejecuta el comando en / bin / sh. Este es el comportamiento del ejecutivo y el sistema de Perl con un argumento, pero solo si el argumento contiene caracteres especiales.Versión sin golf
fuente