쉘에서 문자열을 나누고 마지막 필드를 얻는 방법


293

문자열 1:2:3:4:5이 있고 마지막 필드 ( 5이 경우) 를 가져오고 싶다고 가정하십시오 . Bash를 사용하여 어떻게합니까? 시도했지만으로 cut마지막 필드를 지정하는 방법을 모르겠습니다 -f.

답변:


430

문자열 연산자 를 사용할 수 있습니다 .

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5

이것은 전면에서 ':'까지 탐욕스럽게 모든 것을 다듬습니다.

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }

7
이 문제가 주어진 문제에 대해 작동하는 동안 아래의 William의 답변 ( stackoverflow.com/a/3163857/520162 ) 5은 문자열이 1:2:3:4:5:(문자열 연산자를 사용하는 동안 빈 결과를 생성하는 경우 ) 반환 합니다 . 마무리 /문자를 포함하거나 포함하지 않을 수있는 경로를 구문 분석 할 때 특히 유용 합니다.
eckes

9
그러면 어떻게이 반대를 하시겠습니까? '1 : 2 : 3 : 4 :'를 출력하려면?
Dobz

12
그리고 마지막 분리기 전에 어떻게 부품을 유지합니까? 분명히을 사용하여 ${foo%:*}. #-처음부터; %-끝에서. #, %- 짧은 일치; ##, %%-가장 긴 일치.
Mihai Danila

1
경로에서 마지막 요소를 얻으려면 어떻게 사용해야합니까? echo ${pwd##*/}작동하지 않습니다.
Putnik

2
@Putnik 해당 명령 pwd은 변수로 간주 됩니다. 시도하십시오 dir=$(pwd); echo ${dir##*/}. 나를 위해 작동합니다!
Stan Strum

344

또 다른 방법은 전후를 뒤집는 것입니다 cut.

$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef

이렇게하면 마지막 필드 하나만 또는 끝에서 번호가 매겨진 필드 범위를 매우 쉽게 얻을 수 있습니다.


17
이 대답은 저자가 이미 잘 알고있는 '잘라 내기'를 사용하기 때문에 좋습니다. 때문에 플러스, 나는이 대답을 좋아하는 나는 따라서 검색을 통해이 스레드를 발견,이 정확한 질문을 '컷'을 사용하고 있었다입니다.
Dannid

6
공백을 구분자로 사용하는 사람들을위한 잘라 내기 및 붙여 넣기 사료 :echo "1 2 3 4" | rev | cut -d " " -f1 | rev
funroll

2
레브 | 컷 -d -f1 | 레브는 너무 영리합니다! 감사! 나를 도와주었습니다 (사용 사례는 rev | -d ''-f 2- | rev
EdgeCaseBerg

1
나는 항상 잊어 버렸습니다 rev. cut -b20- | rev | cut -b10- | rev
shearn89

나는 공백을 포함한 파일 이름도 떨어져 절단했기 때문에, "AWK의 -F"잘라 파일 경로 오 내 시도 / " '{$ NF를 인쇄}' '이 솔루션 결국 나를 위해 다소 파산
THX

76

cut을 사용하여 마지막 필드를 얻는 것은 어렵지만 awk 및 perl의 솔루션은 다음과 같습니다.

echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'

5
허용 된 답변에 비해이 솔루션의 큰 장점 : 마무리 /문자 를 포함하거나 포함하지 않는 경로와 일치 /a/b/c/d하며 처리 할 때 /a/b/c/d/동일한 결과 ( d)를 생성 pwd | awk -F/ '{print $NF}'합니다. /a/b/c/d/
eckes

@eckes GNU bash의 AWK 솔루션의 경우 버전 4.3.48 (1)-릴리스는 슬래시가있을 때마다 중요하기 때문에 사실이 아닙니다. 간단히 AWK는 /구분 기호로 사용 되며 경로가 /my/path/dir/마지막 구분 기호 뒤에 값을 사용합니다. 이는 단순히 빈 문자열입니다. 따라서 내가하는 것과 같은 일을 해야하는 경우 슬래시를 피하는 것이 가장 좋습니다.
stamster

마지막 필드까지 하위 문자열을 어떻게 얻습니까?
blackjacx

1
@blackjacx 몇 가지 단점이 있지만, awk '{$NF=""; print $0}' FS=: OFS=:종종 비슷한 기능이 충분합니다.
윌리엄 퍼셀

29

상당히 간단한 사용법 (예를 들어 구분 기호를 이스케이프 처리하지 않음)을 가정하면 grep을 사용할 수 있습니다.

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5

분류-줄 끝 ($)에서 분리 문자 ([^ :])가 아닌 모든 문자를 찾으십시오. -o는 일치하는 부분 만 인쇄합니다.


-E는 확장 구문을 사용함을 의미합니다. [^ ...]는 나열된 문자 이외의 것을 의미합니다. + 하나 이상의 이러한 적중 (패턴에 가능한 최대 길이가 필요합니다.이 항목은 gnu 확장자입니다)-예를 들어 분리 문자는 콜론입니다.
Alexander Stohr

18

일방 통행:

var1="1:2:3:4:5"
var2=${var1##*:}

또 하나는 배열을 사용합니다.

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}

또 다른 배열 :

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}

Bash (버전> = 3.2) 정규식 사용 :

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}

11
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

구분 기호를 줄 바꿈으로 변환하고로 마지막 항목을 선택하십시오 tail -1.


마지막 항목에가 포함되어 있으면 실패 \n하지만 대부분의 경우 가장 읽기 쉬운 솔루션입니다.
Yajo

7

사용 sed:

$ echo '1:2:3:4:5' | sed 's/.*://' # => 5

$ echo '' | sed 's/.*://' # => (empty)

$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c

$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c

4

마지막 필드가 단일 문자 인 경우 다음을 수행 할 수 있습니다.

a="1:2:3:4:5"

echo ${a: -1}
echo ${a:(-1)}

bash에서 문자열 조작을 확인하십시오 .


작동하지 않습니다 : 마지막 필드가 아닌의 마지막 문자 를 제공합니다 . a
gniourf_gniourf

1
사실, 그것이 마지막 아이디어의 길이를 알고 있다면 좋습니다. 그렇지 않다면 다른 것을 사용해야한다면 ...
Ab Irato

4

여기에는 많은 좋은 답변이 있지만 여전히 basename을 사용 하여이 답변을 공유하고 싶습니다 .

 basename $(echo "a:b:c:d:e" | tr ':' '/')

그러나 문자열에 이미 '/'가 있으면 실패합니다. . 슬래시 /가 구분 기호 인 경우 basename을 사용해야합니다.

가장 좋은 대답은 아니지만 bash 명령을 사용하여 창의력을 발휘하는 방법을 보여줍니다.


2

배쉬 사용하기.

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \$${#}
0

echo ${!#}대신 사용할 수 있습니다 eval echo \$${#}.
Rafa

2
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

먼저 xargs를 사용하여 ":"을 사용하여 분할하십시오. -n1은 모든 행에 하나의 파트 만 있음을 의미합니다.


1
for x in `echo $str | tr ";" "\n"`; do echo $x; done

2
필드에 공백이 있으면 문제가 발생합니다. 또한 마지막 필드 를 검색하는 문제를 직접 다루지는 않습니다 .
chepner 2016 년

1

Python에 익숙한 사람들에게는 https://github.com/Russell91/pythonpy 가이 문제를 해결하는 좋은 선택입니다.

$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'

pythonpy 도움말에서 : -x treat each row of stdin as x.

이 도구를 사용하면 입력에 적용되는 파이썬 코드를 쉽게 작성할 수 있습니다.


1

간단한 해결책은 입력 문자열의 순서를 반대로하는 것이지만 대답에 약간 늦을 수 있습니다. 이렇게하면 길이에 관계없이 항상 마지막 항목을 얻을 수 있습니다.

[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5

그러나이 방법을 사용하고 숫자가 1 자리보다 크거나 (어떤 상황에서든 한 문자보다 큰 경우) 파이프 출력에 대해 다른 'rev'명령을 실행해야합니다.

[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24

내가 도울 수 있기를 바랍니다


1

내장 된 읽기를 사용하는 솔루션 :

IFS=':' read -a fields <<< "1:2:3:4:5"
echo "${fields[4]}"

또는 더 일반적인 것으로 만들려면

echo "${fields[-1]}" # prints the last item

0

파이썬을 좋아하고 패키지를 설치할 수있는 옵션이 있다면 이 파이썬 유틸리티를 사용할 수 있습니다 .

# install pythonp
pythonp -m pip install pythonp

echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5

파이썬은 이것을 직접 할 수 있습니다 : echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
MortenB

@MortenB 당신은 착각합니다. pythonp패키지 의 전체 목적은 python -c더 적은 문자 입력과 동일한 작업을 수행하는 것 입니다. 저장소의 README를 살펴보십시오.
폭탄

0

정규식 일치 sed는 욕심이 많으며 (항상 마지막 항목으로 이동) 다음과 같은 이점을 얻을 수 있습니다.

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.