web-dev-qa-db-fra.com

Comment utiliser une variable d'environnement dans une chaîne entre guillemets dans Bash

J'ai essayé différentes formes de ce qui suit dans un script bash:

#!/bin/bash
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Mais je ne peux pas obtenir la syntaxe pour développer correctement la variable d’environnement COLUMNS.

J'ai essayé différentes formes de ce qui suit:

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W $COLUMNS'

et

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W ${COLUMNS}'

et

eval svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Suggestions?

80
Jamie

En cas de doute, vous pouvez utiliser la requête 'cols' sur le terminal et oublier COLUMNS:

COLS=$(tput cols)
15
TheBonsai

Juste une petite note/résumé pour tous ceux qui sont venus ici via Google à la recherche de la réponse à la question générale posée dans le titre (comme j’étais). N'importe lequel des éléments suivants devrait permettre d'accéder aux variables Shell à l'intérieur de guillemets:

echo "$VARIABLE"
echo "${VARIABLE}"

L'utilisation de guillemets simples est le problème principal. Selon le Manuel de référence Bash :

Caractères entre guillemets simples (') préserve la valeur littérale de chaque caractère dans les guillemets. Un seul guillemet ne peut pas apparaître entre guillemets, même s'il est précédé d'une barre oblique inverse. [...] Caractères entre guillemets (") préserve la valeur littérale de tous les caractères compris entre guillemets, à l'exception de $, `, \ et lorsque le développement de l'historique est activé, !. Les personnages $ et `conservent leur signification particulière entre guillemets (voir Expansions Shell). La barre oblique inverse ne conserve sa signification particulière que si elle est suivie de l’un des caractères suivants: $, `, ", \, ou nouvelle ligne. Dans les guillemets doubles, les barres obliques inverses suivies de l'un de ces caractères sont supprimées. Les barres obliques inverses précédant les caractères sans signification particulière ne sont pas modifiées. Une citation double peut être citée entre guillemets en la faisant précéder d'une barre oblique inverse. Si activé, l’extension de l’historique sera réalisée sauf si un ! apparaissant entre guillemets est échappé en utilisant une barre oblique inverse. La barre oblique inverse précédant le ! n'est pas supprimé. Les paramètres spéciaux * et @ ont une signification particulière entre guillemets doubles (voir Extension des paramètres de shell).

Dans le cas spécifique posé dans la question, $ COLUMNS est une variable spéciale qui possède des propriétés non standard (voir la réponse de lhunath ci-dessus).

350
RecursivelyIronic

Notez que COLUMNS est:

  1. PAS une variable d'environnement. C'est un paramètre bash ordinaire défini par bash lui-même.
  2. Défini automatiquement à la réception d'un signal SIGWINCH.

Ce deuxième point signifie généralement que votre variable COLUMNS ne sera définie que dans votre shell interactif , non dans un script bash.

Si le stdin de votre script est connecté à votre terminal, vous pouvez rechercher manuellement la largeur de votre terminal en demandant à votre terminal:

tput cols

Et pour utiliser ceci dans votre commande SVN:

svn diff "$@" --diff-cmd /usr/bin/diff -x "-y -w -p -W $(tput cols)"

(Remarque: vous devriez citer "$@" et restez loin de eval ;-))

13
lhunath

Le script suivant fonctionne pour moi pour plusieurs valeurs de $COLUMNS. Je me demande si vous ne définissez pas COLUMNS avant cet appel?

#!/bin/bash
COLUMNS=30
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Pouvez-vous faire écho $COLUMNS dans votre script pour voir s’il est réglé correctement?

1
Alex B

Vous le faites bien, alors je suppose que quelque chose d'autre est en cause (ne pas exporter des colonnes?).

Une astuce pour déboguer ces cas est de faire une commande spécialisée (une fermeture pour les gars du langage de programmation). Créez un script Shell nommé diff-columns faisant:

exec /usr/bin/diff -x -y -w -p -W "$COLUMNS" "$@"

et juste utiliser

svn diff "$@" --diff-cmd  diff-columns

De cette façon, votre code est plus propre à la lecture et plus modulaire (approche top-down), et vous pouvez tester le code diff-colonnes séparément (approche bottom-up).

0
Colas Nahaboo