Próbuję wydrukować dwa ciągi znaków oddzielone TAB. Próbowałem:
echo -e 'foo\tbar'
printf '%s\t%s\n' foo bar
Oba drukują:
foo bar
Gdzie biała spacja między nimi wynosi w rzeczywistości 5 spacji (zgodnie z wyborem wyjścia za pomocą myszy w Putty).
Próbowałem również użyć CTRL + V i naciskając TAB podczas wpisywania polecenia, z tym samym rezultatem.
Jaki jest właściwy sposób na wymuszenie drukowania tabulatora jako tabulatora, dzięki czemu mogę wybrać wynik i skopiować go w inne miejsce, używając tabulatorów?
I drugie pytanie: dlaczego bash rozwija tabulatory w spacje?
Aktualizacja : Najwyraźniej jest to problem Putty: /superuser/656838/how-to-make-putty-display-tabs-within-a-file-instead-of-changing-them-to -przestrzenie
bash
putty
whitespace
tabs
Asu
źródło
źródło
printf '%s\\t%s\n' foo bar
foo\tbar
...$'\t'
jako tabulator. Możesz więc zawsze łączyć takie ciągi znaków - na przykład jako zadanie:v='This is'$'\t''a test'
I drukować dosłownie, np.printf '%s' "$v"
Odpowiedzi:
Jak powiedział ilkkachu, nie jest to problem z bash, ale z emulatorem terminala, który konwertuje tabulatory na spacje na wyjściu.
Sprawdzanie różnych terminali, putty, xterm i konsoli zamienia tabulatory na spacje, podczas gdy urxvt i gnome-terminal nie. Kolejnym rozwiązaniem jest zmiana terminali.
źródło
stty tab3
.Nie, nie jest. Brak danych wyjściowych
echo
lubprintf
.To inny problem. Nie chodzi o powłokę, ale emulator terminala, który konwertuje tabulatory na spacje na wyjściu. Wielu, ale nie wszyscy to robią.
Może być łatwiej przekierować dane wyjściowe z tabulatorami do pliku i skopiować je stamtąd lub użyć
unexpand
na wyjściu do konwersji spacji na tabulatory. (Chociaż nie może również wiedzieć, od czego na początku były białe znaki, i jeśli to możliwe, przekonwertuje je na tabulatory). To oczywiście zależeć będzie od tego, co dokładnie trzeba zrobić z wydrukiem.źródło
W
printf '%s\t%s\n' foo bar
,printf
robi wyjściefoo<TAB>bar<LF>
.f
,o
,b
,a
Ir
są to pojedyncze szerokości znaków graficznych.Po otrzymaniu tych znaków terminal wyświetli odpowiedni glif i przesunie kursor o jedną kolumnę w prawo, chyba że osiągnął już prawą krawędź ekranu (papier w oryginalnych maszynach do pisania na maszynie)), w którym to przypadku może podać linię i wróć do lewej krawędzi ekranu (zawiń) lub po prostu odrzuć znak w zależności od terminala i jego konfiguracji.
<Tab>
i<LF>
są dwoma znakami kontrolnymi .<LF>
(aka newline) to separator linii w tekście uniksowym, ale dla terminali po prostu podaje linię (przesuń kursor o jedną pozycję w dół). Tak więc sterownik terminala w jądrze faktycznie go przetłumaczy<CR>
(powrót do lewej krawędzi ekranu),<LF>
(kursor w dół) (stty onlcr
zazwyczaj domyślnie włączony).<Tab>
mówi terminalowi, aby przesunął kursor do następnego tabulatora (który w większości terminali jest domyślnie oddalony o 8 pozycji, ale można go również skonfigurować do ustawienia w dowolnym miejscu) bez wypełniania odstępu pustymi miejscami.Jeśli więc te znaki są wysyłane do terminala z tabulatorami co 8 kolumn, gdy kursor znajduje się na początku pustej linii, spowoduje to:
wydrukowany na ekranie w tej linii. Jeśli zostaną wysłane, gdy kursor znajduje się na trzeciej pozycji w linii zawierającej
xxxxyyyyzzzz
, spowoduje to:W terminalach, które nie obsługują tabulacji, sterownik terminala można skonfigurować tak, aby tłumaczył te tabulatory na sekwencje spacji. (
stty tab3
).Znak SPC w oryginalnych maszynach do pisania przesuwałby kursor w prawo, a backspace (
\b
) - w lewo. Teraz w nowoczesnych terminalach SPC przesuwa się w prawo, a także usuwa (zapisuje spację, jak można się spodziewać). Dlatego wisiorek\b
musiał być czymś nowszym niż ASCII. W większości nowoczesnych terminali, to faktycznie ciągiem znaków:<Esc>
,[
,C
.Dostępnych jest więcej sekwencji ucieczki do przesuwania
n
postaci w lewo, w prawo, w górę, w dół lub w dowolnej pozycji na ekranie. Istnieją inne sekwencje specjalne do wymazywania (wypełniania pustych) części linii lub obszarów ekranu itp.Sekwencje te są zazwyczaj używane przez aplikacje wizualnych, takich jak
vi
,lynx
,mutt
,dialog
gdzie tekst jest napisany w dowolnych pozycjach na ekranie.Teraz wszystkie emulatory terminali X11 i kilka innych niż X11, takie jak GNU,
screen
pozwalają wybrać obszary ekranu do wklejenia. Po wybraniu części tego, co widzisz wvi
edytorze, nie chcesz kopiować wszystkich sekwencji specjalnych, które zostały użyte do wytworzenia tego wyniku. Chcesz zaznaczyć tekst, który tam widzisz.Na przykład, jeśli uruchomisz:
Który symuluje sesji edytora gdzie można wejść
abC
, wróć do początku, wymienićab
zAC
,C
zB
, przejść do następnego tabulatora, a następnie jeszcze jedną kolumnę w prawo, a następnie dwie kolumny po lewej stronie, a następnie wprowadzićD
.Zobaczysz:
To znaczy,
ABC
4-kolumnowa przerwa iD
.Jeśli wybierzesz tę opcję za pomocą myszy w
xterm
lubputty
, będą one przechowywać w zaznaczeniuABC
4 znaki spacji, aD
nieabC<CR>AC<BS>B<Tab><Esc>[C<BS><BS>D
.To, co kończy się w selekcji, to to, co zostało wysłane,
printf
ale przetworzone przez sterownik terminala i emulator terminala.W przypadku innych rodzajów transformacji zobacz
<U+0065><U+0301>
(e
następnie łączący ostry akcent) zmieniony na<U+00E9>
(é
forma wstępnie skomponowana) przezxterm
.Lub
echo abc
to ostatecznie zostanie przetłumaczoneABC
przez kierowcę terminala przed wysłaniem do terminala postty olcuc
.Teraz,
<Tab>
podobnie jak<LF>
jeden z niewielu znaków kontrolnych, które tak naprawdę czasami znajdują się w plikach tekstowych (także<CR>
w plikach tekstowych MSDOS, a czasem<FF>
do podziału strony).Tak więc niektóre emulatory terminali decydują się na kopiowanie ich, gdy jest to możliwe, w buforach kopiuj-wklej, aby je zachować (generalnie tak nie jest
<CR>
ani tak<LF>
nie jest).Na przykład, w terminalach opartych na VTE, takich jak
gnome-terminal
, możesz zobaczyć, że kiedy wybierzesz wyjścieprintf 'a\tb\n'
w pustym wierszu,gnome-terminal
faktycznie zapisujesza\tb
wybór X11 zamiasta
7 spacji ib
.Ale na wyjściu
printf 'a\t\bb\n'
, przechowujea
, 6 pomieszczeń ib
, a dlaprintf 'a\r\tb\n'
,a
7 miejsc ib
.Istnieją inne przypadki, w których terminale spróbują skopiować rzeczywiste dane wejściowe, na przykład po wybraniu dwóch linii po uruchomieniu, w
printf 'a \nb\n'
których zostanie zachowana niewidoczna końcowa przestrzeń. Lub przy wyborze dwóch linii nie zawiera znaku LF, gdy dwie linie wynikają z zawijania na prawym marginesie.Teraz, jeśli chcesz zapisać dane wyjściowe
printf
w SCHOWKUX11
wybierz, najlepiej zrobić to bezpośrednio, jak w przypadku:Należy pamiętać, że po wklejeniu, że w
xterm
przypadku większości innych terminali,xterm
faktycznie zastępuje\n
się\r
bo to postaćxterm
wysyła po naciśnięciu Enter(i kierowca terminal może przełożyć go z powrotem\n
).źródło
X11
to, co obsługuje wybór kopiuj-wklej w emulatorach terminali, takich jakxterm
lubputty
na Uniksie. Inne emulatory terminali mogą mieć własny mechanizm kopiuj-wklej i sposoby przechowywania dowolnych treści, takich jak poleceniareadbuf
iregister
na ekranie GNU.