Znak ASCII separatora jednostek (ASCII 31, ósemka 37) jest widoczny w Vimie jako ^_
. Ale jeśli wydrukuję ten sam plik na terminalu, znak będzie niewidoczny. Powoduje to, że pola linii łączą się ze sobą:
# In Vim and less:
first field^_second field^_last field
# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field
# print 2nd field with awk
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field
Przypuszczam, że mogę sprawić, by separator jednostek był widoczny za pomocą cat -v:
cat -v delim.txt
first field^_second field^_last field
Ale to raczej kłopotliwe. Dlaczego separator jednostek nie ma widocznej reprezentacji po wydrukowaniu na standardowe wyjście w powłoce Bash? Nie mogę nawet poprawnie skopiować i wkleić danych wyjściowych powłoki; separator jednostek gubi się w tym procesie.
Odpowiedzi:
Znak separatora jednostek (
US
), znany również jakoIS1
, należy docntrl
klasy znaków i nie należy doprint
klasy znaków. Jest to znak kontrolny, który jest przeznaczony do organizowania tekstu w grupy, w programach zaprojektowanych do korzystania z tych informacji . Zasadniczo znaki niedrukowalne będą prawdopodobnie interpretowane i renderowane inaczej w różnych programach lub środowiskach.Powodem, dla którego widzisz go reprezentowanego jak
^_
w Vimie, jest to, że Vim jest interaktywnym edytorem. Może dowolnie renderować znaki niedrukowalne, o ile chce, pod warunkiem, że na dysk zapisany jest prawidłowy znak binarny.Nie można uzyskać takiego samego zachowania w powłoce, ponieważ programy powłoki w systemie Unix są napisane, aby działać i przekazywać sobie nawzajem zwykły tekst. Gdy masz
cat
plik, tekst zapisany w terminalu musi być tym, co faktycznie znajduje się w pliku.Pozostawia to urządzeniu końcowym interpretację znaku. I okazuje się, że niektóre emulatory terminali zrobić renderowania
US
charakter odmienny od innych. Wgnome-terminal
(lub dowolnymvte
terminalu bazowym) znak będzie renderowany jako ramka zawierająca kod szesnastkowy001F
. Wxterm
lubrxvt
postać jest rzeczywiście niewidoczna.źródło
US
jest całkowicie niewidoczny. Kiedy wstawię ten znak do terminala za pomocąCtrl+/
(potwierdzonego przez<C-v><C-/>
), usuwa nieprzewidywalną ilość tekstu w linii. Nie do końca rozumiem jego zachowanie, ale wydaje się, że ma głównie pewien efekt „odwracania tabulatorów”, w którym zamiast wstawiać spacje, usuwa liczbę znaków, ale czasami czasami losowo wstawia tekst, więc jest to mylące .Separator jednostek należy do zakresu znaków kontrolnych ASCII , a zatem nie ma (lub zwykle nie powinien) przedstawiać wizualnie.
Vim i niektóre inne edytory wyświetlają je, więc możesz je edytować. Jak zauważyłeś,
cat -v
wyświetla również. Strona-v
podręcznika pokazuje, że jest to krótka forma--show-nonprinting
, która powoduje, że zastępuje ona znaki niedrukowalne reprezentacją do wydrukowania, która nie jest oryginalną zawartością pliku i dlatego może powodować problemy, jeśli dane wyjściowe są w rzeczywistości w innym programie .Reprezentacja, którą już widzisz, wskazuje, że jest to znak kontrolny: znak poprzedzony znakiem a
^
jest powszechną notacją Ctrlznaku +, który jest kombinacją klawiszy, która tworzy ten znak w terminalu. Ctrl+ _pozwoli ci na przykład wprowadzić separator jednostek w vimie. Ale inny edytor lub przeglądarka GUI może wyświetlać kod szesnastkowy, symbol zastępczy lub coś zupełnie innego.Ponieważ twój terminal nie drukuje znaków kontrolnych, nie jest również kopiowany podczas zaznaczania tekstu (znaki białych znaków, takie jak nowa linia i tab, są tutaj wyjątkiem, które również są znakami kontrolnymi). Innym przykładem znaków kontrolnych w terminalu, które są zwykle ignorowane podczas kopiowania, są kody kolorów, które są
ESC
znakami, po których następuje kod do kolorowania tekstu.Aby więc wyświetlić znaki na terminalu, nie ma innego sposobu niż użycie programu, który zamienia separator jednostek na znak do wydruku.
źródło
Trochę na marginesie innych (bardzo dobrych) odpowiedzi, jeśli chcesz zmienić tylko znak kontrolny
^_
podczas wyświetlania zawartości pliku, możesz chcieć transliterować go za pomocątr
narzędzia (i trochę składni kompatybilnej z bash) :Jeśli musisz zastąpić ten znak kontrolny jego „rozwiniętą” postacią, musisz
sed
zamiast tego:Zwróć uwagę na składnię
$'\cX'
: ta składnia informuje twoją (powłokę kompatybilną z bash), aby zastąpić odpowiedni znak kontrolny. Zobacz wikipedię, aby uzyskać listę aliasów znaków kontrolnych używających „notacji karetki”. Jeśli nie podoba ci się ta składnia, możesz zamiast tego użyć notacji ósemkowej$'\037'
lub szesnastkowej$'\x1f'
.źródło