Caractères de tabulation d'écho dans le script bash

313

Comment puis-je faire écho à un ou plusieurs tabulations à l'aide d'un script bash? Quand j'exécute ce code

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

j'ai compris

res=[ x] # that is [<space>x]
kalyanji
la source

Réponses:

530
echo -e ' \t '

fera écho à «new tab space space» ( -esignifie «permettre l'interprétation des échappements antislash»):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
Johannes Weiss
la source
Merci Johannes. Vous m'avez aidé à trouver cette solution: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji
2
Savez-vous par hasard pourquoi echo -ene fonctionne pas à partir de Makefiles?
dma_k
23
C'est parce que ce echo -en'est pas POSIX et les makeappels /bin/shqui ne sont normalement pas utilisés de manière interactive par le programme et qui ne sont normalement pas -eimplémentés. Pour la portabilité, utilisez printf '\t'plutôt.
Jo So
Dans Darwin (macOS), la manpage de la echocommande ne mentionne pas l'option -e. Cependant, cette option est acceptée.
ePi272314
75

Utilisez printfpas echo.

Il existe plusieurs versions différentes de la echocommande. Il y en a /bin/echo(qui peut être ou non la version GNU Coreutils, selon le système), et la echocommande est intégrée dans la plupart des shells. Différentes versions ont différentes manières (ou aucune manière) de spécifier ou de désactiver les échappements pour les caractères de contrôle.

printf, d'autre part, a beaucoup moins de variation. Il peut exister en tant que commande, généralement /bin/printf, et il est intégré à certains shells (bash et zsh l'ont, tcsh et ksh ne le font pas), mais les différentes versions sont beaucoup plus similaires les unes aux autres que les différentes versions de echo. Et vous n'avez pas à vous souvenir des options de ligne de commande (à quelques exceptions près; GNU Coreutils printf accepte --versionet --help, et le bash printf intégré accepte -v varde stocker la sortie dans une variable).

Pour votre exemple:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

Et maintenant, il est temps pour moi d'admettre que echocela fonctionnera aussi bien pour l'exemple dont vous parlez; il vous suffit de mettre des guillemets autour de l'argument:

echo "[$res]"

comme l'a écrit kmkaplan (il y a deux ans et demi, je viens de le remarquer!). Le problème avec vos commandes d'origine:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

n'est pas avec echo; c'est que la coquille a remplacé la languette par un espace avant de la echovoir.

echoest bien pour une sortie simple, comme echo hello world, mais vous devez utiliser printfchaque fois que vous voulez faire quelque chose de plus complexe. Vous pouvez vous mettre echoau travail, mais le code résultant est susceptible d'échouer lorsque vous l'exécutez avec une echoimplémentation différente ou un shell différent.

Keith Thompson
la source
1
J'ai aimé celui-ci, il me permet d'utiliser les connaissances de printf et de tous les spécificateurs de format.
Arun
@JezenThomas: Il n'est pas plus voté car il répond à la question d'une autre manière que celle demandée. La question mentionne spécifiquement l'écho, et l'écho n'est pas un verbe mais une commande.
Paulo Neves
@PauloNeves: Je dirais qu'il est utilisé comme verbe dans la question: "Comment puis-je faire écho à un ou plusieurs tabulations en utilisant un script bash?"
Keith Thompson
34

Mettez votre chaîne entre guillemets doubles :

echo "[$res]"
kmkaplan
la source
1
même ici - c'est ce que j'ai essayé en premier. -e a bien fonctionné cependant
froderik
2
@kmkaplan Fonctionne pour moi dans zsh - échoue pour moi dans bash
Kal
34

Vous pouvez également essayer:

echo Hello$'\t'world.
jbatista
la source
4
+1 pour une solution plus générale. J'utilise bash depuis des années et je viens de l'apprendre maintenant!
Aryeh Leib Taurog
C'est une réponse beaucoup plus générale que la réponse acceptée car elle peut être utilisée sans écho.
jwan
22

vous devez utiliser le drapeau -e pour l'écho, vous pouvez

echo -e "\t\t x"
Apprentissage
la source
16

Depuis la page de manuel de bash:

Les mots de la forme $ 'string' sont traités spécialement. Le mot se développe en chaîne, avec des caractères d'échappement antislash remplacés comme spécifié par la norme C ANSI.

Vous pouvez donc faire ceci:

echo $'hello\tworld'
esoriano
la source
Pourquoi cela fonctionne-t-il sur le cli mais pas dans un script bash?
Freek
13

Utilisez la combinaison de touches mot pour mot, ^V( CTRL+V, C-v, peu importe ).

Lorsque vous tapez ^Vdans le terminal (ou dans la plupart des éditeurs Unix), le caractère suivant est repris mot pour mot . Vous pouvez l'utiliser pour taper un caractère de tabulation littéral dans une chaîne que vous faites écho.

Quelque chose comme les œuvres suivantes:

echo "^V<tab>"     # CTRL+V, TAB

Bash docs ( qv , "quoted-insert")

quoted-insert (Cq, Cv) Ajoutez le caractère suivant que vous tapez à la ligne mot pour mot. Voici comment insérer des séquences de touches comme Cq, par exemple.

note de côté: selon cela, ALT+TAB devrait faire la même chose, mais nous avons tous lié cette séquence à la commutation de fenêtre afin que nous ne puissions pas l'utiliser

tab-insert (M-TAB) Insère un caractère de tabulation.

-

Remarque: vous pouvez utiliser cette stratégie avec toutes sortes de personnages inhabituels. Comme un retour chariot:

echo "^V^M"        # CTRL+V, CTRL+M

En effet, le retour chariot est ASCII 13 et M est la 13e lettre de l'alphabet, donc lorsque vous tapez ^M, vous obtenez le 13e caractère ASCII. Vous pouvez le voir en action en utilisant ls^M, à une invite vide, qui insérera un retour chariot, provoquant l'invite à agir exactement comme vous appuyez sur retour. Lorsque ces caractères sont normalement interprétés, textuellement vous obtenez le caractère littéral.

riche souvenir
la source
1
J'aimerais pouvoir vous donner plus de votes positifs pour celui-ci. Je ne voulais pas utiliser un -e dans mes arguments dans ce cas, et cela fonctionne très bien. Merci!
Aaron R.
"... la plupart des éditeurs Unix"? J'ai essayé d'entrer ceci avec vi et emacs et cela n'a pas donné les résultats souhaités non plus.
GreenMatt
C'est tellement cool! Et sauvé ma journée en essayant d'utiliser greppour attraper des lignes contenant des tabcaractères.
Joël
11

L'utilisation de l'écho pour imprimer les valeurs des variables est un piège Bash courant. Lien de référence:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo

Anonyme
la source
Cool, j'aime les "BashPitfalls", un super morceau de matière et soulage beaucoup de douleur de mon travail quotidien!
Jerry Tian
+1 parce que c'est tellement vrai. Mais notez que la chaîne kalyanji commence par un «[» et ne contient aucun «\».
kmkaplan
2

Si vous souhaitez utiliser echo "a\tb"dans un script, vous exécutez le script en tant que:

# sh -e myscript.sh

Vous pouvez également donner à myscript.sh l'autorisation d'exécution, puis exécuter le script.

# chmod +x myscript.sh
# ./myscript.sh
ATC
la source
0
res="\t\tx"
echo -e "[${res}]"
yanghaogn
la source