'cut'을 사용하여 마지막 필드를 찾는 방법


310

없이 사용 sed하거나 awk, 전용 cut 필드의 수는 모든 라인에 알 수없는하거나 변경할 때, 어떻게 마지막 필드를받을 수 있나요?


8
당신은 cut명령 과 사랑에 빠졌 습니까 :)? 왜 다른 리눅스 명령이 아닌가?
Jayesh Bhoi

7
sed또는 없이 awk: perl -pe 's/^.+\s+([^\s]+)$/$1/'.
jordanm


4
@MestreLion 많은 사람들이 문제의 변형에 대한 해결책을 찾기 위해 질문을 읽습니다. 이것은 cut그렇지 않은 것을 지원 하는 잘못된 전제로 시작 합니다. 그러나 독자가 따르기 쉬운 코드를 독자가 강요해야한다는 점에서 유용하다고 생각했습니다. 내가 사용하는 빠르고 간단한 방법을 원하는 cut여러 구문을 사용하지 않고 awk, grep, sed, 등 rev일이 트릭 않았다; 매우 우아하고 내가 고려하지 않은 것 (다른 상황에서 어색한 경우에도). 나는 또한 다른 답변에서 다른 접근법을 읽는 것을 좋아했습니다.
Beejor

3
실제 문제가 발생했습니다. 소스 트리에서 .gitattributes 파일을 업데이트하기 위해 모든 다른 파일 확장자를 찾고 싶습니다. 그래서 find | cut -d. -f<last>자연적인 성향이다
studog는

답변:


679

다음과 같이 시도해보십시오.

echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev

설명

  • rev "maps.google.com"을 반대로 moc.elgoog.spam
  • cut 점 (예 : '.')을 구분 기호로 사용하고 첫 번째 필드를 선택합니다. moc
  • 마지막으로 다시 뒤집기 위해 com

6
사용 cut하지 않고 sed또는 없이 사용됩니다. awkOP는 어떻게 생각합니까?
Jayesh Bhoi

7
@tom OP는 지난 몇 시간 동안 이보다 더 많은 질문을했습니다. OP와의 상호 작용을 바탕으로 awk / sed / etc 등을 알고 있습니다. 그의 숙제에는 허용되지 않지만 rev에 대한 언급은 이루어지지 않았다. 그래서 그것은 가치가 있었다
zedfoxus

4
@zfus 알겠습니다. rev나중에 다른 것을 붙이고 싶을 수도 있습니다.
tom

17
두 배 rev큰 이상!
포드 구오

6
굉장하고 간단하며 완벽합니다. 설명해 주셔서 감사합니다. 파이프 명령의 긴 체인에서 각 단계를 설명하는 사람들이 충분하지 않습니다
Pete

128

매개 변수 확장을 사용하십시오. 이것은 훨씬 더 효율적 어떤 외부 명령의 종류보다 cut(또는 grep포함).

data=foo,bar,baz,qux
last=${data##*,}

bash의 기본 문자열 조작에 대한 소개는 BashFAQ # 100 을 참조하십시오 .


3
@ ErwinWessels : bash는 실제로 느리기 때문입니다. 대량으로 데이터를 처리하지 않고 파이프 라인을 실행하려면 bash를 사용하십시오. 쉘 변수에 이미 한 줄의 텍스트가 있거나 while IFS= read -ra array_var; do :;done <(cmd)몇 줄을 처리 하려는 경우에 좋습니다 . 그러나 큰 파일의 경우 rev | cut | rev가 더 빠를 것입니다! (물론 awk가 그것보다 빠를 것입니다.)
Peter Cordes

2
@PeterCordes, awk는 큰 파일의 경우 더 빠를 것이지만, 일정한 요소 시작 비용을 극복하려면 상당한 입력이 필요합니다. (ksh93과 같이 awk에 가까운 성능을 가진 쉘도 있습니다.이 답변에 제공된 구문은 유효합니다 .bash는 매우 느리지 만 사용 가능한 유일한 옵션에 가깝지는 않습니다).
Charles Duffy

1
감사합니다 @PeterCordes; 평소처럼 각 도구에는 사용 사례가 있다고 생각합니다.
Erwin Wessels

1
이것은 bash스크립트 내에서 단일 변수를 트리밍하는 가장 빠르고 간결한 방법입니다 (이미 bash스크립트를 사용하고 있다고 가정 ). 외부 적으로 전화 할 필요가 없습니다.
Ken Sharp

1
@Balmipour, ... 그러나, rev 이다 그게 제공 어떤 OS 사용중인 특정 - 그것은 모든 유닉스 시스템에서 표준화 아니에요. 명령 및 유틸리티에 대한 POSIX 섹션에 대한 장 목록을 참조하십시오 . 그리고 실제로 배쉬 전용 ${var##prefix_pattern}아닙니다 . 그것은 POSIX sh 표준에 있으며, 섹션 2.6.2의 끝 부분을 참조하십시오 rev.
Charles Duffy

89

를 사용하는 것은 불가능합니다 cut. 사용하는 방법은 다음과 같습니다 grep.

grep -o '[^,]*$'

다른 분리 문자의 경우 쉼표를 바꾸십시오.


3
반대로, 마지막 필드를 제외한 모든 것을 찾으려면 :grep -o '^.*,'
Ariel

2
rev필자의 경우 문제 멀티 바이트 유니 코드 문자를 추가 하기 때문에 특히 유용했습니다 .
Brice

3
MinGW 에서이 작업을 시도했지만 grep 버전이 -o를 지원하지 않으므로 sed 's/^.*,//'마지막 쉼표를 포함한 모든 문자를 빈 문자열로 바꿉니다.
TamaMcGlinn

46

awk없이? ... 그러나 awk로 너무 간단합니다.

echo 'maps.google.com' | awk -F. '{print $NF}'

AWK는 주머니에 더 강력한 도구입니다. 필드 구분 기호 NF가 필드 수인 경우 -F (마지막 인덱스도 나타냄)


2
이것은 보편적이며 매번 예상대로 정확하게 작동합니다. 이 시나리오 cut에서 OP의 최종 결과물을 얻기 위해 숟가락을 사용하여 스테이크를 자르는 것과 같습니다 (pun 예정 :)). awk스테이크 나이프입니다.
Hickory420

3
불필요하게 사용 echo하면 긴 파일의 스크립트 속도가 느려질 수 있습니다 awk -F. '{print $NF}' <<< 'maps.google.com'.
Anil_M

14

여러 가지 방법이 있습니다. 이것도 사용할 수 있습니다.

echo "Your string here"| tr ' ' '\n' | tail -n1
> here

분명히 tr 명령의 공백 입력은 필요한 구분 기호로 바꿔야합니다.


감사합니다! busybox sh 1.0.0에서 작동하는 것 :)
kevinf

1
이것은 나에게 가장 간단한 대답, 적은 파이프와 더 명확한 의미처럼 느껴집니다
joeButler

1
전체 파일에는 작동하지 않으므로 OP가 의미하는 것입니다.
Amir

7

이것은 컷 이외의 것을 사용할 수있는 유일한 솔루션입니다.

에코 "문자열"| 컷 -d '.' -f2- [repeat_following_part_forever_or_until_out_of_memory :] | 컷 -d '.' -f2-

이 솔루션을 사용하면 실제로 필드 수를 알 수 없으며 때때로 달라질 수 있습니다. 그러나 줄 길이는 개행 문자를 포함하여 LINE_MAX 문자 또는 필드를 초과해서는 안되므로 임의의 수의 필드를이 솔루션의 실제 조건으로 포함 할 수 없습니다.

예, 매우 바보 같은 솔루션이지만 내가 생각하는 기준을 충족시키는 유일한 솔루션입니다.


2
좋은. 마지막 '.' "문자열"에서이 작동합니다.
Matt

2
나는 모든 사람들이 무언가가 불가능하다고 말하고 누군가가 일하는 대답으로 차임하는 것을 좋아합니다. 실제로 매우 어리석은 경우에도 마찬가지입니다.
Beejor

cut -f2-출력이 더 이상 변경되지 않을 때까지 루프에서 반복 할 수 있습니다 .
loa_in_ 2016 년

4

입력 문자열에 슬래시가 포함되어 있지 않으면 basename서브 쉘을 사용할 수 있습니다 .

$ basename "$(echo 'maps.google.com' | tr '.' '/')"

이것은 사용하지 않는 sedawk뿐만 아니라 사용하지 않는 cut내가 확신 그것의 말로으로 질문에 대한 답변으로 자격이 있는지 아니에요, 그래서 하나.

슬래시를 포함 할 수있는 입력 문자열을 처리하는 경우에는 제대로 작동하지 않습니다. 이 상황에 대한 해결 방법은 슬래시를 유효한 입력 문자열의 일부가 아닌 다른 문자로 바꾸는 것입니다. 예를 들어 파이프 ( |) 문자는 파일 이름에 사용할 수 없으므로 다음과 같이 작동합니다.

$ basename "$(echo 'maps.google.com/some/url/things' | tr '/' '|' | tr '.' '/')" | tr '|' '/'


0

다음과 같은 목록 경로 인 filelist.txt라는 파일이있는 경우 c : /dir1/dir2/file1.h c : /dir1/dir2/dir3/file2.h

다음을 수행 할 수 있습니다. rev filelist.txt | 컷 -d "/"-f1 | 신부님


0

재미를 위해이 오래된 질문에 대한 접근 방식을 추가하십시오.

$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info

$ cat tmp.sh # showing off the script to do the job
#!/bin/bash
delim=';'
while read -r line; do  
    while [[ "$line" =~ "$delim" ]]; do
        line=$(cut -d"$delim" -f 2- <<<"$line")
    done
    echo "$line"
done < input.file

$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info

bash 외에도 cut 만 사용됩니다. 음, 반향합니다.


Meh, 컷을 완전히 제거하고 bash를 사용하지 않는 이유는 무엇입니까? x] while read -r line; do echo ${line/*;}; done <input.file같은 결과를 낳습니다.
Kaffe Myers

-1

후행 구분 기호가 있는지 확인하면 작동합니다. 그래서 내 경우에는 쉼표와 공백 구분 기호가 있습니다. 끝에 공백을 추가합니다.

$ ans="a, b"
$ ans+=" "; echo ${ans} | tr ',' ' ' | tr -s ' ' | cut -d' ' -f2
b

그리고 "필드 수를 알 수 없거나 모든 라인마다 변경됩니다" 의 요구 사항을 충족하지 않는 ans="a, b, c"produce를 생성합니다 . b
jww
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.