2013-07-09 2 views
73

Я написал следующие строки, чтобы получить последний символ строки:Как получить последний символ строки в оболочке?

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

Он работает на abcd/:

$ bash last_ch.sh abcd/ 
/

Это не работает для abcd*:

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

В нем перечислены файлы в текущей папке..

ответ

44

Это одна из причин, почему вы должны привести переменные:

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

В противном случае, Баш расширяет переменный и в этом случае не подстановки перед печатью вне. Кроме того, лучше процитировать параметр в скрипт (в случае, если у вас есть соответствующий имя файла):

sh lash_ch.sh 'abcde*' 

см также порядок разложения в bash reference manual. Переменные расширяются до расширения имени файла.

+42

BTW, подсчитывать отрицательные индексы справа, так ' "$ {1: -1}"' достаточно. – choroba

+3

Вы должны ответить как официальное решение, а не в комментариях. – BMW

+0

FYI: вы также можете сделать это в «одном слое» как «echo» $ {str: $ (($ {# str} -1)): 1} "'. Это позволяет также изменять возвращаемые символы. Эта работа для меня в bash v4.1.0 (1) – SaxDaddy

128

Per @perreal, цитируя переменные имеет важное значение, но потому, что я прочитал этот пост, как 5 раз, прежде чем найти более простой подход к рассматриваемому вопросу в комментариях ...

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

Выход: /

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

Выход: *

Спасибо всем, кто принимал участие в этом выше; Я правильно добавил +1 к потоку!

+13

NB: обратите внимание на пространство внутри '$ {std: -1}', без пробела это не сработает. Я столкнулся с этим и обнаружил, что '$ {std: ~ 0}' также работает (с пространством или без него). Не уверен, что это документированное поведение, хотя я не потрудился разобраться. – Bart

+2

документировано. man bash говорит: Арифметические выражения, начинающиеся с символа - должны быть разделены пробелами из предыдущего: чтобы отличаться от значения Использовать значения по умолчанию – mighq

+2

Это потрясающе, спасибо за обмен. Масштабирование BASH почти непреодолимо для чтения, хотя я был там несколько раз. Я думаю, что они могут сделать курс колледжа вокруг сценария оболочки. – quickshiftin

2

другое решение с использованием AWK сценария:

последних 1 полукокс:

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

последних 5 символов:

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

Однолинейные:

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

Сейчас:

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

Почему вы используете две пары круглых скобок? Кроме того, начиная с 4.2, вы можете использовать отрицательные смещения, как показано в ответе quickshiftin: 'echo '$ {str: -1}" 'достаточно (разумеем пробел между': 'и' -'). –

+0

Для арифметических операций используются две пары круглых скобок. –

+0

№. См. [Соответствующую часть руководства] (http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion) где вы будете читать: _length_ и _offset_ - арифметические выражения (см. [Арифметика оболочки] (http://www.gnu.org/software/bash/manual/bash.html#Shell-Arithmetic)); поэтому вы уже находитесь в арифметике оболочки и вообще не нуждаетесь в круглых скобках. Кроме того, если бы вы сказали, что это правда, было бы логичнее иметь _арифметическое расширение_ с '$ ((...))'. –

15

Я знаю, что это очень старая нить, но никто не говорил что для меня это самый чистый ответ:

echo -n $str | tail -c 1 

Обратите внимание на -n просто так эхо не включает в себя новую строку в конце.

+5

Даже близко к чистоте, чем $ {str: -1} – shrewmouse

2

Каждый ответ до сих пор подразумевает слово "оболочки" в вопросе приравнивает к Bash.

Это, как можно было бы сделать в стандартной оболочке Bourne:

printf $str | tail -c 1 
Смежные вопросы