쉘에서 문자열의 마지막 문자를 얻는 방법은 무엇입니까?


125

문자열의 마지막 문자를 얻기 위해 다음 줄을 작성했습니다.

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

그것은 현재 폴더에있는 파일을 나열합니다 .

답변:


96

이것이 변수를 인용해야하는 이유 중 하나입니다.

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

그렇지 않으면 bash는 변수를 확장하고이 경우 인쇄하기 전에 globbing을 수행합니다. 매개 변수를 스크립트에 인용하는 것이 좋습니다 (일치하는 파일 이름이있는 경우).

sh lash_ch.sh 'abcde*'

bash 참조 매뉴얼 의 확장 순서도 참조하십시오 . 변수는 파일 이름 확장 전에 확장됩니다.

마지막 문자를 얻으려면 -1음수 인덱스가 문자열의 끝에서 계산되므로 인덱스로 사용해야 합니다.

echo "${str: -1}"

콜론 ( :) 뒤의 공백 은 필수입니다.

이 접근 방식은 공간 없이는 작동하지 않습니다.


62
BTW, 음수 지수는 오른쪽에서 계산하므로 "${1: -1}"충분합니다.
choroba

7
여기 댓글이 아닌 공식적인 해결책으로 답장해야합니다.
BMW

참고 : "one-liner"에서 echo "${str:$((${#str}-1)):1}". 이렇게하면 반환되는 후행 문자도 변경할 수 있습니다. 이 작업은 bash v4.1.0 (1)
SaxDaddy

16
@choroba의 대답 : 빌어 먹을 공간에 유의하십시오! 이것은 항상 나를 "${1:-1}
괴롭힌다

192

@perreal에 따르면 변수를 인용하는 것이 중요하지만 주석에서 당면한 질문에 대한 더 간단한 접근 방식을 찾기 전에이 게시물을 5 번 읽었 기 때문에 ...

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

산출: /

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

산출: *

위에 참여 해주신 모든 분들께 감사드립니다. 스레드 전체에 적절하게 +1을 추가했습니다!


25
NB : 내부 공간에 유의하십시오 ${std: -1}. 공간이 없으면 작동하지 않습니다. 나는 이것을 만났고 ${std:~0}(공간이 있든 없든) 작동 한다는 것을 발견했습니다 . 이것이 문서화 된 행동인지 확실하지 않지만 나는 그것을 찾는 것을 귀찮게하지 않았습니다.
Bart

4
문서화되어 있습니다. man bash는 다음과 같이 말합니다.-로 시작하는 산술 표현식은 앞의 공백으로 구분해야합니다. Use Default Values ​​확장과 구별하기 위해
mighq

3
훌륭합니다. 공유해 주셔서 감사합니다. BASH 맨 페이지는 읽기에 거의 압도적이지만 나는 거기에 여러 번 있었다. 나는 그들이 쉘 스크립팅을 중심으로 대학 과정을 만들 수 있다고 생각합니다.
quickshiftin 2014

3
이 솔루션은 .sh검색된 문자를 변수에 할당하려고 할 때 스크립트 에서 작동하지 않습니다 . 예를 들어 declare LAST=$(echo "${str: -1}") 다음에서 시작하는 구문 오류를 표시하는 불쾌한 빨간색 막대가 나타납니다.
krb686

3
편집기 구문 검사가 해당 공간을 좋아하지 않는 경우 시도${str:0-1}
ttt

36

나는 이것이 매우 오래된 스레드라는 것을 알고 있지만 아무도 나에게 가장 깨끗한 대답이라고 언급하지 않았습니다.

echo -n $str | tail -c 1

(가) 주 -n에코가 마지막에 개행 문자가 포함되어 있지 않습니다 만, 그래서이다.


15
$ {str : -1}보다 깨끗하지도 않습니다
shrewmouse

8
bash-ism에 의존하지 않으므로 더 깨끗하므로 모든 Posix 쉘에서 작동합니다.
John Eikenberry

가장 "바시 스트"는 무엇입니까? "$ {str : -1}"그리고 ... 가장 깨끗한 것은 무엇입니까? "$ {str : -1}"Bash가 가장 좋습니다! :-)
Roger

큰 파일에 마지막 문자를 인쇄하려는 사람에게는이 작업이 수행되었습니다. cat user / folder / file.json | tail -c 1 1을 인쇄 할 문자 수로 바꿀 수 있습니다.
Diego Serrano

5

awk 스크립트를 사용하는 또 다른 솔루션 :

마지막 1 자 :

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

마지막 5 자 :

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

1
OP가 요청한 것은 아니지만 이것이 파일과 함께 사용되는 것으로 확인 된 최고의 솔루션입니다. 대부분의 다른 접근 방식은 다음과 같이 파일을 검색하지 못합니다. cat file | awk '{print substr($0,length,1)}'감사합니다!
xmar aug

4

한 줄:

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

지금:

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

1
두 쌍의 괄호를 사용하는 이유는 무엇입니까? 또한, 4.2 이후, 당신은 quickshiftin의 대답에 표시된 부정적인 오프셋을 사용할 수 있습니다 : echo "${str: -1}"(사이의 공간을 마음 충분 :하고 -).
gniourf_gniourf 2015 년

산술 연산에 두 쌍의 괄호가 사용됩니다.
Eduardo Cuomo

아니요. 읽을 수 있는 설명서의 관련 부분을 참조하십시오 . 길이오프셋 은 산술 표현식입니다 ( 셸 산술 참조 ). 따라서 이미 셸 산술을 사용하고 있으며 괄호가 전혀 필요하지 않습니다. 게다가, 당신이 말한 것이 사실이라면, 산술 확장 을 갖는 것이 더 논리적 일 것 입니다 $((...)).
gniourf_gniourf 2015 년

@gniourf_gniourf 맞아요! 이제 이전 질문을 이해했습니다. 답변 업데이트
Eduardo Cuomo

4

지금까지의 모든 대답은 질문에서 "shell"이라는 단어가 Bash와 동일하다는 것을 의미합니다.

이것은 표준 Bourne 쉘에서이를 수행하는 방법입니다.

printf $str | tail -c 1

1
echo -nuser5394399가 제안한대로 $str특수 형식 문자를 포함 할 때 문제를 방지 합니다.
Conrad Meyer

-n스위치는 bashism이다. 표준 Bourne 셸에서는 대시 등으로 작동하지 않습니다. 내 대답의 요점이었습니다.
phep

1
bashism은 아니지만 POSIX는 구현이 정의되어 있음을 인식합니다 ( "첫 번째 피연산자가 -n이거나 피연산자에 <백 슬래시> 문자가 포함 된 경우 결과는 구현 정의 됨"). 대신 printf "%s" "$str" | ...:-)로 대답을 수정할 수 있습니다 .
Conrad Meyer

4

시험:

"${str:$((${#str}-1)):1}"

예 :

someone@mypc:~$ str="A random string*"; echo "$str"
A random string*
someone@mypc:~$ echo "${str:$((${#str}-1)):1}"
*
someone@mypc:~$ echo "${str:$((${#str}-2)):1}"
g

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.