Pour accélérer l'exécution de scripts bash, j'aimerais conserver le résultat d'une commande dans une variable utilisant la substitution de commande, mais cette substitution remplace le caractère de début de ligne 0x0A
par un espace. Par exemple:
a=`df -H`
ou
a=$( df -H )
Lorsque je veux traiter davantage $a
, les caractères de nouvelle ligne sont remplacés par un espace et toutes les lignes sont maintenant sur une ligne, ce qui est beaucoup plus difficile à grep:
echo $a
Quels seraient les trucs faciles pour éviter que le caractère de nouvelle ligne ne soit supprimé par la substitution de commande?
Les nouvelles lignes que vous recherchez sont là, vous ne les voyez pas, car vous utilisez echo
sans citer la variable.
Validation:
$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 276G 50G 213G 19% /
udev 2.1G 4.1k 2.1G 1% /dev
tmpfs 832M 820k 832M 1% /run
none 5.3M 0 5.3M 0% /run/lock
none 2.1G 320k 2.1G 1% /run/shm
$
Comme @ user4815162342 l'a correctement souligné, bien que les nouvelles lignes de la sortie ne soient pas supprimées, nouvelles lignes suivies sont supprimées avec substitution de commande. Voir l'expérience ci-dessous:
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
Dans la plupart des cas, cela n'a pas d'importance, car echo
ajoutera la nouvelle ligne supprimée (sauf si elle est invoquée avec l'option -n
). Cependant, dans certains cas Edge, la sortie d'un programme contient plus d'une nouvelle ligne, significatif pour une raison quelconque.
Dans ce cas, comme indiqué par @Scrutinizer, vous pouvez utiliser la solution de contournement suivante:
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
Explication: _ Le caractère x
est ajouté à la sortie (à l'aide de printf x
), après les nouvelles lignes. Comme les nouvelles lignes ne sont plus fin, elles ne sont pas supprimées par la substitution de commande. L'étape suivante consiste à supprimer le x
que nous avons ajouté à l'aide de l'opérateur %
dans ${a%x}
. Maintenant nous avons la sortie originale, avec toutes les nouvelles lignes présentes !!!
Au lieu d'utiliser la substitution de commande pour affecter la sortie d'un programme à une variable, nous pouvons utiliser plutôt substitution de processus pour alimenter la sortie du programme avec la commande intégrée read
(crédit de @ormaaj). La substitution de processus préserve toutes les nouvelles lignes. Lire le résultat sur une variable est un peu délicat, mais vous pouvez le faire comme ceci:
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
Explication:
IFS=
. Sinon, read
n'affecterait pas la sortie entière à var
, mais uniquement le premier jeton.read
avec les options -rd ''
. r
permet d'éviter que la barre oblique inversée agisse comme un caractère spécial. Avec d ''
, définissez le délimiteur sur néant de sorte que la lecture soit lue dans son intégralité au lieu de la première ligne.Au lieu d'utiliser une substitution de commande ou de processus pour affecter la sortie d'un programme à une variable, nous pouvons diriger la sortie du programme vers la commande read
(crédit de @ormaaj). La tuyauterie préserve également toutes les nouvelles lignes. Notez toutefois que cette fois-ci, nous définissons le comportement optionnel du shell lastpipe
en utilisant le __ intégré shopt
. Cela est nécessaire pour que la commande read
soit exécutée dans l'environnement Shell actuel. Sinon, la variable sera affectée dans un sous-shell et ne sera pas accessible à partir du reste du script.
$ cat test.sh
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$
J'essayais de comprendre cela parce que j'utilisais bash pour diffuser le résultat de l'exécution de l'interpréteur sur un script F #. Après quelques essais et erreurs, nous avons résolu le problème:
$ cat fsi.ch
#!/bin/bash
echo "$(fsharpi --quiet --exec --nologo $1)"
$ fsi.ch messages.fsx
Welcome to my program. Choose from the menu:
new | show | remove
En supposant, bien sûr, que vous ayez besoin de lancer un programme terminal . J'espère que cela vous aidera.