Odpowiedzi:
Ostatnie trzy znaki string
:
${string: -3}
lub
${string:(-3)}
(zwróć uwagę na odstęp między :
iw -3
pierwszej formie).
Proszę odnieść się do Rozszerzenia parametrów powłoki w podręczniku referencyjnym :
${parameter:offset}
${parameter:offset:length}
Expands to up to length characters of parameter starting at the character
specified by offset. If length is omitted, expands to the substring of parameter
starting at the character specified by offset. length and offset are arithmetic
expressions (see Shell Arithmetic). This is referred to as Substring Expansion.
If offset evaluates to a number less than zero, the value is used as an offset
from the end of the value of parameter. If length evaluates to a number less than
zero, and parameter is not ‘@’ and not an indexed or associative array, it is
interpreted as an offset from the end of the value of parameter rather than a
number of characters, and the expansion is the characters between the two
offsets. If parameter is ‘@’, the result is length positional parameters
beginning at offset. If parameter is an indexed array name subscripted by ‘@’ or
‘*’, the result is the length members of the array beginning with
${parameter[offset]}. A negative offset is taken relative to one greater than the
maximum index of the specified array. Substring expansion applied to an
associative array produces undefined results.
Note that a negative offset must be separated from the colon by at least one
space to avoid being confused with the ‘:-’ expansion. Substring indexing is
zero-based unless the positional parameters are used, in which case the indexing
starts at 1 by default. If offset is 0, and the positional parameters are used,
$@ is prefixed to the list.
Ponieważ ta odpowiedź ma kilka regularnych wyświetleń, pozwolę sobie dodać możliwość odniesienia się do komentarza Johna Rixa ; jak wspomina, jeśli twój łańcuch ma długość mniejszą niż 3, ${string: -3}
rozwija się do pustego łańcucha. Jeśli w tym przypadku chcesz rozbudować string
, możesz użyć:
${string:${#string}<3?0:-3}
Używa ?:
potrójnego operatora if, który może być użyty w arytmetyce powłoki ; ponieważ zgodnie z dokumentacją offset jest wyrażeniem arytmetycznym, jest to poprawne.
deppfx@localhost:/tmp$ echo ${$(hostname): -3}
-bash: ${$(hostname): -3}: bad substitution
temp=$(hostname); echo "${temp: -3}"
. Bash ma również HOSTNAME
zmienną (która może, ale nie musi, różnić się od wyniku hostname
). Jeśli chcesz go użyć, po prostu zrób echo "${HOSTNAME: -3}"
.
some func | echo ${string: -3}
- jak przypisać wyjście some func
do string
?
string=$(some func)
i wtedy echo "${string: -3}"
.
Możesz użyć tail
:
$ foo="1234567890"
$ echo -n $foo | tail -c 3
890
Dość okrężnym sposobem na uzyskanie trzech ostatnich znaków byłoby powiedzenie:
echo $foo | rev | cut -c1-3 | rev
Innym obejściem jest użycie grep -o
niewielkiej magii wyrażeń regularnych, aby uzyskać trzy znaki, po których następuje koniec wiersza:
$ foo=1234567890
$ echo $foo | grep -o ...$
890
Aby opcjonalnie uzyskać od 1 do 3 ostatnich znaków, w przypadku łańcuchów zawierających mniej niż 3 znaki, możesz użyć egrep
tego wyrażenia regularnego:
$ echo a | egrep -o '.{1,3}$'
a
$ echo ab | egrep -o '.{1,3}$'
ab
$ echo abc | egrep -o '.{1,3}$'
abc
$ echo abcd | egrep -o '.{1,3}$'
bcd
Możesz także użyć różnych zakresów, na przykład 5,10
uzyskać od pięciu do dziesięciu ostatnich znaków.
Aby uogólnić pytanie i odpowiedź gniourf_gniourf (ponieważ właśnie tego szukałem), jeśli chcesz wyciąć zakres znaków od, powiedzmy, 7 od końca do 3 od końca, możesz użyć tej składni:
${string: -7:4}
Gdzie 4 to długość kursu (7-3).
Ponadto, chociaż rozwiązanie gniourf_gniourf jest oczywiście najlepsze i najładniejsze, chciałem tylko dodać alternatywne rozwiązanie wykorzystujące cięcie :
echo $string | cut -c $((${#string}-2))-$((${#string}))
Jest to bardziej czytelne, jeśli zrobisz to w dwóch wierszach, definiując długość $ {# string} jako oddzielną zmienną.
cut
podejścia polegającego na obliczeniu początku / zatrzymania najpierw, a następnie po prostu przy użyciu tych zmiennych w rozwinięciu parametrów (warto również wspomnieć, że cut
i przesunięcia basha zaczynają się odpowiednio od 1 i zera, więc wymagałoby to do uwzględnienia w obliczeniach, których tutaj nie robię): start=$((${#string}-3)); stop=$((${#string}));
a następnie echo ${string: $start : $stop}
vsecho $string | cut -c "$start"-"$stop"