8
votes

Comment conserver les espaces lors de l'enregistrement de la sortie de commande dans une variable Makefile?

J'ai connaissance de questions telles que celui-ci , mais ma question porte spécifiquement sur makefile, en particulier gnumake.

J'ai une commande qui imprime les sauts de ligne et autres espaces en standard. Je veux capturer cette sortie dans une variable et ensuite imprimer la variable dans un fichier.

Exemple de Makefile:

 _______
< hello >
 -------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Après avoir exécuté make, output. txt contient:

 _______  < hello >  -------          \   ^__^          \  (oo)\_______             (__)\       )\/\                 ||----w |                 ||     ||

Je veux qu'il conserve les espaces et contienne à la place:

OUTPUT=${shell cowsay hello}

all:
    @echo "$(OUTPUT)" > output.txt

La commande que je suis en fait l'utilisation n'est pas une claque, mais elle produit des espaces et des sauts de ligne similaires.


0 commentaires

3 Réponses :


3
votes

C'est une réponse négative, malheureusement. Le GNU Make Manual déclare (soulignement ajouté):

La fonction shell exécute la même fonction que les backquotes exécutent dans la plupart des shells: elle fait extension de commande . Cela signifie qu'il prend comme argument une commande shell et s'évalue à la sortie de la commande. Le seul traitement que make effectue sur le résultat est de convertir chaque nouvelle ligne (ou paire retour chariot / nouvelle ligne) en un seul espace . S'il y a un retour à la ligne (retour chariot et), il sera simplement supprimé.

Je ne pense pas que eval ou define aidera.

La seule solution de contournement que je peux voir est pour stocker la cowsay hello commande dans une variable, au lieu de la sortie de la commande, comme dans:

OUTPUT=$(shell seq 5 | sed s/$$/xxx/)            # add xxx to the end of each line

all:
    @echo -n $(OUTPUT) ' ' | sed 's/xxx /\n/g'   # replace xxx-space with line break

Ce travail -around est mauvais si cowsay hello coûte cher à calculer ou a des effets secondaires. Une deuxième solution consiste à conserver sa sortie, mais à remplacer les sauts de ligne par des caractères arbitraires, en utilisant par exemple sed , puis en ajoutant les sauts de ligne. Par exemple:

OUTPUT=$$(seq 5)     # seq 5 replaces cowsay hello

all:
    @echo "$(OUTPUT)" > output.txt


2 commentaires

Une autre solution simple consiste à stocker la sortie dans un fichier en premier lieu.


Edit: L'idée de substitution a également été utilisée dans la réponse de Reinier Torenbeek. Leur réponse est peut-être plus élégante que la mienne, en utilisant tr plutôt que sed .



4
votes

Je veux capturer cette sortie dans une variable et ensuite imprimer le variable dans un fichier.

Il ne semble pas y avoir de moyen de contourner le mécanisme de make pour traduire les retours à la ligne dans la sortie de la commande shell en espaces. Un petit hack qui reste proche de votre approche originale serait de demander au shell de convertir les nouvelles lignes en un caractère inhabituel (comme \ 1 ) lors de l'affectation de la sortie à la variable, puis de la renvoyer quand echo -ing cette variable dans le fichier. Quelque chose comme ceci:

$ make
$ cat output.txt 
 _______ 
< hello >
 ------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Pour moi, cela se traduit par

OUTPUT=$(shell cowsay hello | tr '\n' '\1')

all:
        @echo "$(OUTPUT)" | tr '\1' '\n' > output.txt

1 commentaires

Fugly mais impressionnant. La solution correcte est probablement de ne pas stocker la sortie dans une variable Make.



0
votes

Puisque $ (shell) supprime les nouvelles lignes, remplacez-les simplement par un autre caractère ou motif. Une fois de retour dans make , remplacez ce caractère par une nouvelle ligne.

Ici, j'ai choisi : comme remplacement de nouvelle ligne. YMMV

$ make
Makefile:7: *** [ _______
< hello >
 -------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
].  Stop.

Donner

define \n


endef

cow := $(subst :,${\n},$(shell cowsay hello | tr \\n :))

$(error [${cow}])

Vous trouverez difficile d'utiliser $ {cow} dans les recettes cependant!


0 commentaires