J'ai un script assez simple qui ressemble à ceci:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Lorsque j'exécute ce script à partir de la ligne de commande et lui transmets les arguments, je n'obtiens aucune sortie. Cependant, lorsque j'exécute les commandes contenues dans la $MOREF
variable, je peux obtenir une sortie.
Comment prendre les résultats d'une commande qui doit être exécutée dans un script, l'enregistrer dans une variable, puis afficher cette variable à l'écran?
bash
shell
command-line
John
la source
la source
echo
la variable est une utilisation inutileecho
, et une utilisation inutile de variables.Réponses:
En plus des raccourcis
`command`
, la substitution de commandes peut être effectuée avec$(command)
ou"$(command)"
, que je trouve plus facile à lire, et permet l'imbrication.Quoting (
"
) importe pour conserver les valeurs des variables multilignes ; il est facultatif sur le côté droit d'une affectation, car le fractionnement de mot n'est pas effectué , doncOUTPUT=$(ls -1)
cela fonctionnerait bien.la source
echo
commande.${OUTPUT}foo
. Ils sont également requis lors de l'exécution d'opérations de chaîne en ligne sur la variable, telles que${OUTPUT/foo/bar}
La bonne façon est
Si vous allez utiliser une apostrophe, vous en avez besoin
`
, non'
. Ce personnage est appelé "backticks" (ou "grave accent").Comme ça:
la source
echo
.$()
fonctionne. Impossible de corriger tant que je n'ai pas vu cette page.Quelques astuces Bash que j'utilise pour définir des variables à partir de commandes
2nd Edit 2018-02-12: Ajouté une manière différente, recherchez en bas de celui-ci pour les tâches de longue durée !
25-01-2018 Édition: ajout d'un exemple de fonction (pour remplir les variables sur l'utilisation du disque)
Première méthode simple, ancienne et compatible
Principalement compatible, deuxième voie
L'imbrication pouvant devenir lourde, des parenthèses ont été mises en place pour cette
Échantillon imbriqué:
Lecture de plus d'une variable (avec bashismes )
Si je veux juste une valeur utilisée :
vous pouvez voir une variable de tableau :
Alors:
Mais je préfère ceci:
La première sautera
read foo
simplement la ligne d'en-tête, mais dans une seule commande, vous remplirez 7 variables différentes :Ou même:
... fonctionnera également avec les tableaux associatifs :
read foo disk[total] disk[used] ...
Exemple de fonction pour remplir certaines variables:
Nota: la
declare
ligne n'est pas requise, juste pour la lisibilité.À propos de
sudo cmd | grep ... | cut ...
(S'il vous plaît éviter inutile
cat
! Donc, c'est juste une fourche de moins:Tous les tuyaux (
|
) impliquent des fourches. Où un autre processus doit être exécuté, accès au disque, aux appels de bibliothèques, etc.Donc, utiliser
sed
pour exemple, limitera le sous-processus à une seule fourchette :Et avec les bashismes :
Mais pour de nombreuses actions, principalement sur de petits fichiers, Bash pourrait faire le travail lui-même:
ou
Pour en savoir plus sur le fractionnement variable ...
Jetez un œil à ma réponse à Comment diviser une chaîne sur un délimiteur dans Bash?
Alternative: réduction des fourches en utilisant des tâches de longue durée en arrière-plan
2nd Edit 2018-02-12:
Afin d'éviter plusieurs fourches comme
ou
Cela fonctionne bien, mais l'exécution de nombreuses fourches est lourde et lente.
Et des commandes comme
date
etbc
pourraient faire de nombreuses opérations, ligne par ligne !!Voir:
Nous pourrions donc utiliser un processus d'arrière-plan de longue durée pour effectuer de nombreux travaux, sans avoir à initier un nouveau fork pour chaque demande.
Nous avons juste besoin de descripteurs de fichiers et de fifos pour le faire correctement:
(Bien sûr, FD
5
et6
doivent être inutilisés!) ... À partir de là, vous pouvez utiliser ce processus en:Dans une fonction
newConnector
Vous pouvez trouver ma
newConnector
fonction sur GitHub.Com ou sur mon propre site (Remarque sur GitHub: il y a deux fichiers sur mon site. La fonction et la démo sont regroupées dans un seul fichier qui pourrait être recherché pour être utilisé ou simplement exécuté pour la démo.)Échantillon:
La fonction
myBc
vous permet d'utiliser la tâche d'arrière-plan avec une syntaxe simple et pour la date:De là, si vous souhaitez mettre fin à l'un des processus d'arrière-plan, il vous suffit de fermer son fd :
ce qui n'est pas nécessaire, car tous les fd se ferment à la fin du processus principal.
la source
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
était la déclaration que je cherchais.echo
; vous voulez simplementgrep "$CONTAINER_NAME"
tput
comme tâche d'arrière-plan pour le rendu des couleurs sur le terminal !!kubectl get ns | while read -r line; do echo
$ line | terme grep | cut -d '' -f1; done
imprime pour chacun$line
une ligne vide puisbash: xxxx: command not found
. Cependant, je m'attends à ce qu'il s'imprime justexxx
Comme ils vous l'ont déjà indiqué, vous devez utiliser des «backticks».
L'alternative proposée
$(command)
fonctionne également, et elle est également plus facile à lire, mais notez qu'elle n'est valable qu'avec Bash ou KornShell (et les shells dérivés de ceux-ci), donc si vos scripts doivent être vraiment portables sur divers systèmes Unix, vous devriez préférer l'ancienne notation backticks.la source
$()
est entièrement compatible avec POSIX sh, tel qu'il a été standardisé il y a plus de deux décennies./bin/sh
sur Solaris 10 ne reconnaît toujours pas$(…)
- et AFAIK c'est vrai sur Solaris 11 aussi./bin/sh
trouveksh93
.$()
dans le shell POSIX sur HP-UX depuis plus de 10 ans.Je connais trois façons de le faire:
Les fonctions conviennent à de telles tâches: **
Invoquez-le en disant
func
.Une autre solution appropriée pourrait également être évaluée:
Le troisième utilise directement des variables:
Vous pouvez obtenir la sortie de la troisième solution dans le bon sens:
Et aussi de façon désagréable:
la source
"$var"
bonne et$var
méchante?Juste pour être différent:
la source
Lorsque vous définissez une variable, assurez-vous de n'avoir AUCUN espace avant et / ou après le signe = . J'ai littéralement passé une heure à essayer de comprendre cela, à essayer toutes sortes de solutions! Ce n'est pas cool.
Correct:
Échouera avec l'erreur "stuff: not found" ou similaire
la source
var=value somecommand
fonctionnesomecommand
avecvar
dans son environnement ayant la valeurvalue
. Ainsi,var= somecommand
exportevar
dans l'environnement desomecommand
avec une valeur vide (zéro octet).Si vous voulez le faire avec une ou plusieurs commandes multilignes / multiples, vous pouvez le faire:
Ou:
Exemple:
Production:
En utilisant heredoc , vous pouvez simplifier les choses assez facilement en décomposant votre long code de ligne unique en un code multiligne. Un autre exemple:
la source
bash
à l'intérieur de la substitution de commande? Vous créez déjà un sous-shell par la substitution de commande elle-même. Si vous souhaitez placer plusieurs commandes, séparez-les simplement par un saut de ligne ou un point-virgule.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
serait également «différent»; mais je ne vois pas l'intérêt de cela.ssh
sudo -s
exécuter des commandes mysql à l'intérieur, etc. (au lieu de bash)variable=$(bash -c 'echo "foo"; echo "bar"')
reprisesvariable=$(echo "foo"; echo "bar")
- le document ici n'est qu'un mécanisme de citation et n'ajoute pas vraiment autre chose qu'une autre complication inutile.ssh -p $port $user@$domain /bin/bash <<EOF
afin d'éviter lesPseudo-terminal will not be allocated because stdin is not a terminal.
avertissementsVous devez utiliser soit
$(command-here)
ou
Exemple
la source
$()
est bien meilleur que les backticks. Voir: Quel est l'avantage d'utiliser $ () au lieu de backticks dans les scripts shell?C'est une autre façon et est utile à utiliser avec certains éditeurs de texte qui ne peuvent pas mettre correctement en surbrillance chaque code complexe que vous créez:
la source
Vous pouvez utiliser des backticks (également appelés tombes d'accent) ou
$()
.Comme:
Les deux ont le même effet. Mais OUTPUT = $ (x + 2) est plus lisible et le dernier.
la source
Si la commande que vous essayez d'exécuter échoue, elle écrira la sortie sur le flux d'erreur et sera ensuite imprimée sur la console.
Pour l'éviter, vous devez rediriger le flux d'erreur:
la source
Certains peuvent trouver cela utile. Valeurs entières dans la substitution de variable, où l'astuce consiste à utiliser
$(())
des crochets doubles:la source
for ((...))
boucle semblerait être une meilleure correspondance pour la variable de boucle ). En outre, vous ne devez pas utiliser de majuscules pour vos variables privées.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
mais je suis d'accord avec @tripleee: je ne comprends pas quoi faire, là!Voici deux autres façons:
Veuillez garder à l'esprit que l'espace est très important dans Bash. Donc, si vous voulez que votre commande s'exécute, utilisez-la telle quelle sans introduire plus d'espace.
Cédant suivant
harshil
àL
puis imprimeCe qui suit affecte la sortie de la commande
tr
à L2.tr
est opéré sur une autre variable, L1.la source
$"..."
ne fait probablement pas ce que vous pensez qu'il fait . 2. Ceci est déjà donné dans la réponse d'Andy Lester.echo ${L1,,}
pour downcase ouecho ${L1^^}
upcase.