¿Puedo escribir scripts en C ++?


Recientemente tuve que sumergirme una / otra vez en el maravilloso mundo de la programación de scripts de Linux. En principio, el asunto no es muy complicado, pero dado que me encuentro con tales tareas con poca frecuencia, lo estudio nuevamente cada vez. Sé con certeza que mañana olvidaré mucho y en un mes buscaré en Google nuevamente cómo hacer esto o aquello. El problema sigue siendo que, a menudo, no vuelve a escribir el guión, sino que modifica el existente ya escrito por alguien. Y puede que no sea bash, sino sh u otra cosa ... Hay diferencias en la sintaxis, lo que funciona en sh debería funcionar en bash, pero no siempre al revés. ¿Y si hay rociada o ceniza? No sé ... Todavía hay diferencias en estos lenguajes de script y son confusos. Y, por supuesto, para mí personalmente, la guinda del pastel es cuando el guión llama a algunos sed o awk y hay tales parámetros en la línea de comando que los miras y te preguntas.Está claro que todo esto depende de las calificaciones del programador, pero no todo me cabe en la cabeza. Y ahora mi paciencia se fue y pensé que de ahora en adelante quiero intentar escribir scripts en c ++ ...

Entiendo que para un verdadero administrador del sistema, mi pensamiento puede parecer sedicioso. ¿Pero por qué no?

Entonces la idea es muy simple. Quiero escribir scripts en c ++ de la misma manera que los scripts normales, es decir, la primera línea del script debe contener shebang y una indicación de la ruta al "intérprete":

#!/bin/c++

Las siguientes líneas del script serán solo un programa normal de c ++.

Tengo que preparar el "intérprete" del script c ++. Puedes escribirlo en cualquier cosa, al menos en bash (esta es la última vez, aunque no exactamente). Por supuesto, no será un intérprete, sino un compilador.

Eso fue lo que hice:

#!/bin/bash

msg_file=/dev/null
#msg_file=/dev/stdout

tmp_path=$HOME"/.cache/c++/"
mkdir -p $tmp_path
tmp_file=$1".c++"
exe_file=$1".bin"
if test $1 -nt  $tmp_path$exe_file; then
    echo "Need to recompile.." > $msg_file
    tail -n +2 $1 > $tmp_path$tmp_file
    eval "g++ -o $tmp_path$exe_file $tmp_path$tmp_file > /dev/null 2>&1"
    if [ $? -eq 0 ]
    then
	echo "Compiled ok" > $msg_file
    else
	echo "Compile error" > $msg_file
	exit 255
    fi
fi
eval "$tmp_path$exe_file $@1"

Este script hace todo lo que necesitas. Como carpeta temporal, elegí la carpeta ~ / .cache / c ++. El script original se copiará en esta carpeta, pero sin la primera línea con shebang. Esto se hace mediante el comando de cola. El nombre del nuevo archivo será como el script original, pero con la extensión c ++. El binario con la extensión .bin se recopilará en la misma carpeta. Pero primero, por supuesto, se realiza una comprobación "si prueba" en el momento en que se crea el binario. La compilación se produce solo si el binario existente está desactualizado en el tiempo con respecto al "script" original. El binario se inicia con el comando eval y se le pasan todos los parámetros iniciales.

Este archivo de c ++ debe copiarse en la carpeta / bin y hacerlo ejecutable (chmod a + x).

Intentaré escribir mi primer "script de c ++":

#!/bin/c++

#include <stdio.h>
#include <iostream>

using namespace std;

int main( int argc, char *argv[] )
{
    cout << "hello world!\n";
    for( int i=0; i<argc; i++)
    {
	cout << "Param" << i <<  " is " << argv[i] << "\n";
    }
    return 60+argc;
}

Este programa simplemente imprime una lista de parámetros de entrada y devuelve su número + 60.
Ejecuto mi "script":



¡Funciona!

Si comete un error en el código de c ++, el programa no se iniciará, ya que no se compilará, sino que reflejará $? devolverá 255. Pero eso fue lo que se pretendía.

Usar c ++ brinda enormes oportunidades. Primero, la sintaxis familiar. En segundo lugar, las clases estándar como std :: vector, std :: map o std :: string y otras son cosas irremplazables. La misma línea: haga lo que quiera hacer con ella, mire en la línea, divídala en subcadenas, desconecte y conquiste, obtenga matrices. Y no necesito ni sed ni awk. En tercer lugar, el depurador: ¡Dios! ¡que bendición! ¡Tengo un depurador gdb para el script! Además, puede usar std :: filesystem (si el compilador lo permite). Puedes continuar ...

Desafortunadamente, a menudo sucede conmigo que lo haré primero, y luego pensaré: "¿y si alguien ya ha hecho esto?" Y, de hecho, no soy el primero en tener la idea de hacer lo mismo. Aquí hay un ejemplo: https://github.com/dimgel/cpp-linux-scripts, la idea es la misma, la implementación es diferente. Luego resultó que hay otras implementaciones .

En general, experimenté una ligera decepción en mi propia no exclusividad. Sin embargo, busqué a Habr, no encontré uno similar. Tal vez alguien parece al menos curioso?

All Articles