Posso escrever scripts em C ++?


Recentemente, tive que mergulhar novamente / novamente no maravilhoso mundo da programação de scripts Linux. Em princípio, o assunto não é muito complicado, mas, como não passo muitas vezes essas tarefas, estudo-a novamente todas as vezes. Tenho certeza de que amanhã esquecerei muito e em um mês vou pesquisar novamente no Google como fazer isso ou aquilo. O problema ainda é que muitas vezes você não escreve o script novamente, mas modifica o existente já escrito por alguém. E pode não ser bash, mas sh ou algo mais ... Há diferenças na sintaxe, o que funciona em sh deve funcionar no bash, mas nem sempre o contrário. E se houver traço ou cinzas? Não sei ... ainda existem diferenças nessas linguagens de script e são confusas. E, claro, para mim, pessoalmente, a cereja no topo do bolo quando o script chama sed ou awk e existem parâmetros na linha de comando que você olha para eles e se pergunta.É claro que tudo isso depende das qualificações do programador, mas nem tudo se encaixa na minha cabeça. E agora minha paciência se foi e eu pensei que a partir de agora eu quero tentar escrever scripts em c ++ ...

Entendo que, para um verdadeiro administrador de sistemas, meu pensamento pode parecer sedicioso. Mas porque não?

Então a ideia é muito simples. Quero escrever scripts c ++ da mesma maneira que os scripts regulares, ou seja, a primeira linha do script deve conter shebang e uma indicação do caminho para o "intérprete":

#!/bin/c++

As linhas subsequentes do script serão apenas um programa c ++ regular.

Eu tenho que preparar o "intérprete" do script c ++. Você pode escrever em qualquer coisa, pelo menos no bash (esta é a última vez, embora não exatamente). Obviamente, não será um intérprete, mas um compilador.

Isso é o que eu fiz:

#!/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 faz tudo o que você precisa. Como pasta temporária, escolhi a pasta ~ / .cache / c ++. O script original será copiado para esta pasta, mas sem a primeira linha com shebang. Isso é feito pelo comando tail. O nome do novo arquivo será como o script original, mas com a extensão c ++. O binário com a extensão .bin será coletado na mesma pasta. Mas primeiro, é claro, uma verificação "se teste" é feita no momento em que o binário é criado. A compilação ocorre apenas se o binário existente estiver desatualizado no tempo em relação ao "script" original. O binário é iniciado com o comando eval e todos os parâmetros iniciais são passados ​​para ele.

Esse arquivo c ++ precisa ser copiado para a pasta / bin e o torna executável (chmod a + x).

Vou tentar escrever meu primeiro "script 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 simplesmente imprime uma lista de parâmetros de entrada e retorna seu número + 60. Eu
corro meu "script":



Funciona !!!

Se você cometer um erro no código c ++, o programa não será iniciado, pois não será compilado, mas ecoará $? retornará 255. Mas era isso que se pretendia.

O uso do c ++ oferece enormes oportunidades. Primeiro, a sintaxe familiar. Em segundo lugar, classes padrão como std :: vector, std :: map ou std :: string e outras são coisas insubstituíveis. A mesma linha - o que você quiser fazer com ela, procure na linha, divida-a em substrings, desconecte e conquiste, obtenha matrizes. E eu não preciso nem do sed nem do awk. Terceiro, o depurador - Deus! que benção! Eu tenho um depurador gdb para o script! Além disso, você pode usar o std :: filesystem (se o compilador permitir). Você pode continuar ...

Infelizmente, muitas vezes acontece comigo que eu o farei primeiro e depois pensarei: "e se alguém já fez isso?" E, de fato, não sou o primeiro a ter a idéia de fazer o mesmo. Aqui está um exemplo: https://github.com/dimgel/cpp-linux-scripts a idéia é a mesma, a implementação é diferente. Acontece que existem outras implementações .

Em geral, senti uma pequena decepção por minha própria não exclusividade. No entanto, procurei por Habr - não encontrei um semelhante. Talvez alguém pareça pelo menos curioso?

All Articles