Wat doen \t en \b?

Ik verwacht deze simpele regel code

printf("foo\b\tbar\n");

om “o” te vervangen door “\t” en de volgende uitvoer te produceren

fo     bar

(ervan uitgaande dat tabstop elke 8 tekens voorkomt).
Integendeel, ik krijg

foo    bar

Het lijkt erop dat mijn shell \b interpreteert als “verplaats de cursors één positie terug” en \t als “verplaats de cursor naar de volgende tabstop”. Is dit gedrag specifiek voor de shell waarin ik de code uitvoer? Moet ik ander gedrag verwachten op verschillende systemen?


Antwoord 1, autoriteit 100%

Backspace en tab verplaatsen beide de cursorpositie. Geen van beide is echt een ‘afdrukbaar’ karakter.

Je code zegt:

  1. druk “foo” af
  2. verplaats de cursor één spatie terug
  3. verplaats de cursor naar de volgende tabstop
  4. voer “balk” uit.

Om de output te krijgen die je verwacht, heb je printf("foo\b \tbar")nodig. Let op de extra ‘spatie’. Dat zegt:

  1. voer “foo” uit
  2. verplaats de cursor één spatie terug
  3. voer een ‘ ‘ uit (dit vervangt de tweede ‘o’).
  4. verplaats de cursor naar de volgende tabstop
  5. voer “balk” uit.

Meestal is het ongepast om tabs en backspace te gebruiken voor het formatteren van uw programma-uitvoer. Leer hoe u printf()opmaakspecificaties gebruikt. De weergave van tabbladen kan drastisch variëren, afhankelijk van hoe de uitvoer wordt bekeken.

Dit kleine script toont een manier om de weergave van tabbladen van uw terminal te wijzigen. Getest op Ubuntu + gnome-terminal:

#!/bin/bash
tabs -8 
echo -e "\tnormal tabstop"
for x in `seq 2 10`; do
  tabs $x
  echo -e "\ttabstop=$x"
 done
tabs -8
echo -e "\tnormal tabstop"

Zie ook man settermen regtabs.

En als u uw uitvoer omleidt of gewoon naar een bestand schrijft, worden tabbladen vaak weergegeven als minder dan de standaard 8 tekens, vooral in “programmeer”-editors en IDE’s.

Dus met andere woorden:

printf("%-8s%s", "foo", "bar"); /* this will ALWAYS output "foo     bar" */
printf("foo\tbar"); /* who knows how this will be rendered */

IMHO, tabbladen zijn over het algemeen zelden geschikt voor iets. Een uitzondering kan het genereren van uitvoer zijn voor een programma dat invoerbestanden met door tabs gescheiden waarden vereist (vergelijkbaar met door komma’s gescheiden waarden).

Backspace '\b'is een ander verhaal… het mag nooit worden gebruikt om een tekstbestand te maken, omdat een teksteditor er alleen maar rommel van maakt. Maar het heeft veel toepassingen voor het schrijven van interactieve opdrachtregelprogramma’s die niet kunnen worden bereikt met alleen opmaakstrings. Als je merkt dat je het veel nodig hebt, bekijk dan “ncurses”, waarmee je veel betere controle hebt over waar je uitvoer op het terminalscherm naartoe gaat. En omdat het 2011 is en niet 1995, is een GUI meestal gemakkelijker om mee om te gaan voor zeer interactieve programma’s. Maar nogmaals, er zijn uitzonderingen. Zoals het schrijven van een telnet-server of console voor een nieuwe scripttaal.


Antwoord 2, autoriteit 95%

Nee, daar zijn ze min of meer voor bedoeld.

In C (en veel andere talen) kun je moeilijk te zien/type tekens invoegen met de notatie \:

  • \ais alert/bel
  • \bis backspace/rubout
  • \nis een nieuwe regel
  • \ris regelterugloop (terug naar linkermarge)
  • \tis tabblad

Je kunt ook de octale waarde van elk teken specificeren met \0nnn, of de hexadecimale waarde van elk teken met \xnn.

  • EG: de ASCII-waarde van _is octaal 137, hex 5f, dus het kan ook worden getypt \0137of \x5f, als je toetsenbord geen _-toets of iets dergelijks had. Dit is handiger voor besturingstekens zoals NUL (\0) en ESC (\033)

Zoals iemand heeft gepost (vervolgens zijn antwoord verwijderd voordat ik het een +1 kon geven), zijn er ook enkele minder vaak gebruikte:

  • \fis een formulierinvoer/nieuwe pagina (pagina uit printer verwijderen)
  • \vis een verticaal tabblad (een regel naar beneden gaan, in dezelfde kolom)

Op schermen werkt \fgewoonlijk hetzelfde als \v, maar op sommige printers/teletypes zal het
ga helemaal naar het volgende formulier/vel papier.


Antwoord 3, autoriteit 9%

De C-standaard (eigenlijk C99, ik ben niet up-to-date) zegt:

Alfabetische ontsnappingsreeksen die niet-grafische tekens in de uitvoeringstekenset vertegenwoordigen, zijn bedoeld om als volgt acties op weergaveapparaten te produceren:

\b(backspace)Verplaatst de actieve positie naar de vorige positie op de huidige regel. […]

\t(horizontale tab)Verplaatst de actieve positie naar de volgende horizontale tabulatiepositie op de huidige regel. […]

Beide verplaatsen alleen de actieve positie, geen van beide mag een teken op of over een ander teken schrijven. Om te overschrijven met een spatie kunt u proberen: puts("foo\b \tbar");maar houd er rekening mee dat op sommige weergaveapparaten – bijvoorbeeld een madeliefje-printer – de ozal de transparante ruimte tonen.


Antwoord 4, autoriteit 3%

Dit gedrag is terminal-specifiek en gespecificeerd door de Terminal Emulator die u gebruikt (bijvoorbeeld xterm) en de semantiek van terminal die het biedt. Het terminalgedrag was de afgelopen 20 jaar zeer stabiel en u kunt redelijkerwijs vertrouwen op de semantiek van \b.


Antwoord 5

\tis het tab-teken en doet precies wat u verwacht op basis van de actie van \b– het gaat naar het volgende tabblad wordt verlaagd en gaat dan naar het volgende tabblad (dat in dit geval hetzelfde tabstop is, vanwege de \b.

Other episodes