Znaki tabulacji echa w skrypcie bash

313

Jak wyświetlić echo jednego lub więcej znaków tabulacji za pomocą skryptu bash? Kiedy uruchamiam ten kod

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

rozumiem

res=[ x] # that is [<space>x]
kalyanji
źródło

Odpowiedzi:

529
echo -e ' \t '

wyświetli echo „spacja tabulacja spacja nowa linia” ( -eoznacza „włącz interpretację znaków ukośnika odwrotnego”):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
Johannes Weiss
źródło
Dzięki Johannes. Pomogłeś mi znaleźć to rozwiązanie: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji
2
Czy wiesz, dlaczego echo -enie działa z Makefiles?
dma_k 17.10.10
23
To dlatego, że echo -enie jest POSIX i makewywołania, /bin/shktóre zwykle nie są używane przez program, używają interaktywnie i zwykle nie zostały -ezaimplementowane. Aby zapewnić przenośność, użyj printf '\t'zamiast tego.
Jo So
W Darwin (macOS) manstrona echopolecenia nie wspomina o tej opcji -e. Ta opcja jest jednak akceptowana.
ePi272314
75

Użyj printf, nie echo.

Istnieje wiele różnych wersji echopolecenia. Istnieje /bin/echo(która może, ale nie musi być wersja GNU Coreutils, w zależności od systemu), a echopolecenie jest wbudowane w większość powłok. Różne wersje mają różne sposoby (lub brak możliwości) określenia lub wyłączenia znaków zmiany znaczenia dla znaków kontrolnych.

printfz drugiej strony ma znacznie mniejszą zmienność. Zwykle może istnieć jako polecenie /bin/printfi jest wbudowany w niektóre powłoki (bash i zsh to mają, tcsh i ksh nie), ale różne wersje są znacznie bardziej do siebie podobne niż różne wersje echo. I nie musisz pamiętać opcji wiersza poleceń (z kilkoma wyjątkami; GNU Coreutils printf akceptuje --versioni --help, a wbudowany bash printf akceptuje-v var przechowywanie danych wyjściowych w zmiennej).

Na przykład:

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

A teraz nadszedł czas, żebym przyznał, że echozadziała równie dobrze w przypadku przykładu, o który pytasz; wystarczy wstawić podwójny cudzysłów wokół argumentu:

echo "[$res]"

jak napisał kmkaplan (dwa i pół roku temu, właśnie to zauważyłem!). Problem z oryginalnymi poleceniami:

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

nie jest z echo; polega na tym, że skorupa zastąpiła zakładkę spacją, zanim echoją zobaczyła.

echonadaje się do prostych wyników, takich jak echo hello world, ale powinieneś używać, printfgdy chcesz zrobić coś bardziej złożonego. Ty może dostać echosię do pracy, ale otrzymany kod może zawieść po uruchomieniu go z innej echorealizacji lub innej powłoki.

Keith Thompson
źródło
1
Podobał mi się ten, pozwala mi korzystać z wiedzy o printf i wszystkich specyfikatorach formatu.
Arun,
@JezenThomas: Nie ma większego szacunku, ponieważ odpowiada na pytanie w inny sposób niż wymagany. Pytanie wyraźnie wymienia echo, a echo nie jest czasownikiem, ale poleceniem.
Paulo Neves
@PauloNeves: Powiedziałbym, że jest używany jako czasownik w pytaniu: „Jak mogę echa jednej lub więcej znaków tabulacji za pomocą skryptu bash?”
Keith Thompson
34

Umieść ciąg między podwójnymi cudzysłowami:

echo "[$res]"
kmkaplan
źródło
1
to samo tutaj - tego właśnie próbowałem. -e działało dobrze
froderik
2
@kmkaplan Działa dla mnie w Zsh - kończy się niepowodzeniem w bash
Kal
34

Możesz także spróbować:

echo Hello$'\t'world.
jbatista
źródło
4
+1 za bardziej ogólne rozwiązanie. Używam bash od lat i właśnie się tego nauczyłem!
Aryeh Leib Taurog
Jest to znacznie bardziej ogólna niż zaakceptowana odpowiedź, ponieważ można jej używać bez echa.
jwan
22

musisz użyć flagi -e dla echa, a potem możesz

echo -e "\t\t x"
Uczenie się
źródło
16

Ze strony podręcznika użytkownika bash:

Słowa w postaci $ „string” są traktowane specjalnie. Słowo rozwija się do łańcucha znaków, a znaki specjalne z odwrotnym ukośnikiem są zastępowane zgodnie ze standardem ANSI C.

Możesz to zrobić:

echo $'hello\tworld'
esoriano
źródło
Dlaczego działa to na cli, ale nie w skrypcie bash?
Freek
13

Za pomocą klawiszy verbatim, ^V( CTRL+V, C-v, cokolwiek ).

Podczas pisania ^Vw terminalu (lub w większości edytorów uniksowych) następujący znak jest pobierany dosłownie . Możesz użyć tego do wpisania literowego znaku tabulacji wewnątrz echa łańcucha.

Coś jak następujące prace:

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

Dokumenty Bash ( qv , „quoted-insert”)

quoted-insert (Cq, Cv) Dodaj kolejny wpisany znak do wiersza dosłownie. Oto jak wstawić sekwencje klawiszy, na przykład Cq.

uwaga dodatkowa: zgodnie z tym ALT+TAB powinniśmy zrobić to samo, ale wszyscy związaliśmy tę sekwencję z przełączaniem okien, więc nie możemy jej użyć

tab-insert (M-TAB) Wstaw znak tabulacji.

-

Uwaga: możesz używać tej strategii z różnego rodzaju nietypowymi postaciami. Jak zwrot karetki:

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

Wynika to z faktu, że znak powrotu karetki to ASCII 13, a M to 13 litera alfabetu, więc kiedy piszesz ^M, otrzymujesz 13 znak ASCII. Możesz zobaczyć to w akcji, używając ls^Mpustego monitu, który wstawi znak powrotu karetki, powodując, że będzie on działał tak samo, jak trafiłeś return. Kiedy te znaki są normalnie interpretowane, dosłownie dostajesz dosłowny znak.

bogate przypomnienie
źródło
1
Żałuję, że nie mogę dać więcej głosów na ten temat. W tym przypadku nie chciałem używać -e, a to działa świetnie. Dzięki!
Aaron R.
„... większość edytorów Uniksa”? Próbowałem wprowadzić to zarówno z vi, jak i emacsem, ale nie przyniosło to pożądanych rezultatów.
GreenMatt
To takie fajne! I uratowałem mój dzień, gdy próbowałem użyć grepdo łapania linii zawierających tabznaki.
Joël
11

Używanie echa do drukowania wartości zmiennych jest częstą pułapką Basha. Link referencyjny:

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

Anonimowy
źródło
Fajnie, podoba mi się „BashPitfalls”, świetny materiał i uśmierzam wiele bólu w codziennej pracy!
Jerry Tian
+1, ponieważ jest to tak prawdziwe. Ale zauważ, że ciąg kalyanji zaczyna się od „[” i nie zawiera żadnego „\”.
kmkaplan
2

Jeśli chcesz użyć echo "a\tb"skryptu, uruchom skrypt jako:

# sh -e myscript.sh

Alternatywnie możesz dać myscript.sh uprawnienie do wykonywania, a następnie uruchomić skrypt.

# chmod +x myscript.sh
# ./myscript.sh
ATC
źródło
0
res="\t\tx"
echo -e "[${res}]"
yanghaogn
źródło