Ok, voici celui avec lequel je me bats en ce moment. Faire écho à une commande d'écho avec une variable.
echo "creating new script file."
echo "#!/bin/bash" > $servsfile
echo "read -p "Please enter a service: " ser " >> $servfile
echo "servicetest=`getsebool -a | grep ${ser}` " >> $servfile
echo "if [ $servicetest > /dev/null ];then " >> $servfile
echo "echo "we are now going to work with ${ser}" " >> $servfile
echo "else" >> $servfile
echo "exit 1" >> $servfile
echo "fi" >> $servfile
Mon objectif est de créer un script à l'aide des commandes echo puis de l'exécuter plus tard. J'ai juste besoin de comprendre comment faire écho aux commandes echo/read tout en maintenant mes variables.
edit: les variables doivent transférer ce qu'elles contiennent dans le nouveau fichier.
Le problème immédiat est que vous avez à citer: en utilisant des guillemets doubles, vos références de variables sont instantanément développé , ce qui n'est probablement pas ce que vous voulez.
Utilisez single guillemets à la place - les chaînes à l'intérieur des guillemets simples ne sont pas développées ou interprétées de quelque façon par le shell.
(Si vous voulez sélectif expansion à l'intérieur d'une chaîne - c'est-à-dire, développez certaines références de variables, mais pas d'autres - utilisez des guillemets doubles, mais préfixez le $
Des références que vous faites pas souhaite être développé avec \
; par exemple, \$var
).
Cependant, il vaut mieux utiliser un seul ici-doc [ument], ce qui vous permet de créer plusieurs lignes stdin
entrée sur place, entre crochets par deux instances d'un auto-choisi délimiteur, celui d'ouverture préfixé par <<
, Et la dernière sur une ligne seule - à partir de la toute première colonne; recherchez Here Documents
dans man bash
ou sur http://www.gnu.org/software/bash/manual/html_node/Redirections.html .
Si vous citation le here-doc délimiteur (EOF
dans le code ci-dessous), références variables sont également pas développés . Comme le souligne @chepner, vous êtes libre de choisir la méthode de citation dans ce cas: mettez le délimiteur entre guillemets simples ou guillemets doubles, ou même simplement échapper arbitrairement un caractère dans le délimiteur avec \
:
echo "creating new script file."
cat <<'EOF' > "$servfile"
#!/bin/bash
read -p "Please enter a service: " ser
servicetest=`getsebool -a | grep ${ser}`
if [ $servicetest > /dev/null ]; then
echo "we are now going to work with ${ser}"
else
exit 1
fi
EOF
Comme le note @BruceK, vous pouvez préfixer votre délimiteur ici-doc avec -
(appliqué à cet exemple: <<-"EOF"
) Pour avoir onglets supprimés, permettant une indentation qui rend le contenu réel du document ici plus facile à discerner. Notez, cependant, que cela ne fonctionne qu'avec les caractères tab réels, pas les espaces en tête.
En utilisant cette technique combinée avec les réflexions sur le contenu du script ci-dessous, nous obtenons (encore une fois, notez que tab caractères réels. doit être utilisé pour diriger chaque ligne de contenu ici-doc pour qu'ils soient supprimés):
cat <<-'EOF' > "$servfile"
#!/bin/bash
read -p "Please enter a service name: " ser
if [[ -n $(getsebool -a | grep "${ser}") ]]; then
echo "We are now going to work with ${ser}."
else
exit 1
fi
EOF
Enfin, notez que dans bash
even les chaînes normales entre guillemets simples ou doubles peuvent s'étendre sur plusieurs lignes, mais vous n'obtiendrez pas les avantages de la suppression de tabulation ou du blocage de ligne portée, comme tout à l'intérieur des guillemets devient une partie de la chaîne.
Ainsi, notez comment dans le suivant #!/bin/bash
Doit suivre l'ouverture '
immédiatement pour devenir la première ligne de sortie:
echo '#!/bin/bash
read -p "Please enter a service: " ser
servicetest=$(getsebool -a | grep "${ser}")
if [[ -n $servicetest ]]; then
echo "we are now going to work with ${ser}"
else
exit 1
fi' > "$servfile"
Réflexions sur le contenu de votre script:
$(...)
est préférée à `...`
Pour la substitution de commandes de nos jours.${ser}
Dans la commande grep
, car la commande se cassera probablement si la valeur contient des espaces incorporés (sinon, assurez-vous que la valeur lue ne contient pas d'espaces ou d'autres métacaractères Shell) .[[ -n $servicetest ]]
Pour tester si $servicetest
Est vide (ou effectuez la substitution de commande directement à l'intérieur du conditionnel) - [[ ... ]]
- la forme préférée dans bash
- vous protège de casser le conditionnel si le $servicetest
se trouve avoir des espaces intégrés; il n'est JAMAIS nécessaire de supprimer la sortie stdout dans un conditionnel (que ce soit [ ... ]
ou [[ ... ]]
, car aucune sortie stdout n'est transmise; ainsi, le > /dev/null
est redondant (cela dit, avec une substitution de commande à l'intérieur d'un conditionnel, stderr sortie IS passé).Il vous suffit d'utiliser des guillemets simples:
$ echo "$TEST"
test
$ echo '$TEST'
$TEST
À l'intérieur des guillemets simples, les caractères spéciaux ne sont plus spéciaux, ce ne sont que des caractères normaux.
echo "echo "we are now going to work with ${ser}" " >> $servfile
Échapper tout "entre guillemets avec \. Faites cela avec des variables comme\$ servicetest aussi:
echo "echo \"we are now going to work with \${ser}\" " >> $servfile
echo "read -p \"Please enter a service: \" ser " >> $servfile
echo "if [ \$servicetest > /dev/null ];then " >> $servfile