2013-07-09 11 views
73

Pisałem następujące linie dostać ostatni znak łańcucha:Jak uzyskać ostatni znak ciągu w powłoce?

str=$1 
i=$((${#str}-1)) 
echo ${str:$i:1} 

działa dla abcd/:

$ bash last_ch.sh abcd/ 
/

To nie działa dla abcd*:

$ bash last_ch.sh abcd* 
array.sh assign.sh date.sh dict.sh full_path.sh last_ch.sh 

To wyświetla listę plików w bieżącym folderze..

Odpowiedz

44

To jeden z powodów, dlaczego trzeba zacytować zmienne:

echo "${str:$i:1}" 

Inaczej bash rozszerza zmienną iw tym przypadku nie globbing przed drukowania. Jest także lepiej zacytować parametr do skryptu (w przypadku gdy masz pasujący pliku):

sh lash_ch.sh 'abcde*' 

zobaczyć również kolejność ekspansji w bash reference manual. Zmienne są rozwijane przed rozwinięciem nazwy pliku.

+42

BTW, negatywne wskaźniki liczyć z prawej strony, więc ' "$ {1: -1}"' wystarczy. – choroba

+3

Należy odpowiedzieć jako formalne rozwiązanie, a nie tutaj w komentarzach. – BMW

+0

FYI: możesz również zrobić to w "jednolinijkowym" jako 'echo" $ {str: $ (($ {# str} -1)): 1} "'. Pozwala to na zmianę zwracanych znaków powrotu. Ta praca dla mnie w bash v4.1.0 (1) – SaxDaddy

128

Per @perreal, cytując zmiennych jest ważne, ale ponieważ czytałem ten post jak 5 razy przed znalezieniem uproszczone podejście do kwestii pod ręką w komentarzach ...

str='abcd/' 
echo "${str: -1}" 

wyjściowa: /

str='abcd*' 
echo "${str: -1}" 

wyjściowa: *

Dziękujemy wszystkim, którzy wzięli udział w tym powyżej; Dodałem + 1-ki przez cały wątek!

+13

NB: zanotuj przestrzeń wewnątrz '$ {std: -1}', bez spacji to nie zadziała. Wpadłem na to i odkryłem, że '$ {std: ~ 0}' również działa (z lub bez spacji). Nie jestem pewien, czy to jest udokumentowane zachowanie, nie zadałem sobie trudu, aby to sprawdzić. – Bart

+2

jest to udokumentowane. man bash mówi: Wyrażenia arytmetyczne rozpoczynające się od a - muszą być oddzielone białymi znakami od poprzedzającego: należy odróżnić od rozwinięcia Użyj wartości domyślnych – mighq

+2

To niesamowite, dziękuję za udostępnienie. Strona podręcznika BASH jest prawie przytłaczająca, ale czytałem tam kilka razy. Myślę, że mogliby zrobić kurs college'u wokół skryptów powłoki lol. – quickshiftin

0
echo $str | cut -c $((${#str})) 

jest dobrym podejściem

2

inne rozwiązanie przy użyciu skryptu awk:

ostatnie 1 char:

echo $str | awk '{print substr($0,length,1)}' 

ostatnie 5 znaków:

echo $str | awk '{print substr($0,length-5,5)}' 
2

Pojedyncza linia:

${str:${#str}-1:1} 

Teraz:

echo "${str:${#str}-1:1}" 
+0

Dlaczego używasz dwóch par nawiasów? Ponadto, od 4.2, możesz użyć ujemnych przesunięć, jak pokazano w odpowiedzi quickshiftin: 'echo" $ {str: -1} "' jest wystarczające (pamiętaj o przestrzeni pomiędzy ':' a '-'). –

+0

Dwie pary nawiasów używane są do operacji arytmetycznych –

+0

Nie. Zobacz [odpowiednia część instrukcji] (http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter- Exxpansion) gdzie będziesz czytać: _length_ i _offset_ są wyrażeniami arytmetycznymi (zobacz [arytmetykę powłoki] (http://www.gnu.org/software/bash/manual/bash.html#Shell-Arithmetic)); dlatego już jesteś w arytmetyce powłoki i nie potrzebujesz żadnych nawiasów. Poza tym, gdyby to, co powiedziałeś, było prawdą, bardziej logiczne byłoby mieć _arytmiczne rozszerzenie_ z '$ ((...))'. –

15

Wiem, że to bardzo stary wątek, ale nikt nie wspomniał co dla mnie jest najczystszym odpowiedź:

echo -n $str | tail -c 1 

Zanotuj -n jest tak echo nie zawiera znaku końca na końcu.

+5

Nawet w pobliżu bycia czystszym niż $ {str: -1} – shrewmouse

2

Każda odpowiedź dotychczas implikuje słowo "Shell" w pytaniu przyrównuje do bash.

ten sposób można to zrobić w standardowej powłoki Bourne:

printf $str | tail -c 1 
Powiązane problemy