두 개의 특정 문자 또는 문자열 사이에서 텍스트 찾기


17

다음과 같은 줄이 있다고 가정 해보십시오.

*[234]*
*[23]*
*[1453]*

여기서 *모든 문자열을 나타냅니다 (형식의 문자열 제외 [number]). 명령 행 유틸리티로 이러한 행을 구문 분석하고 대괄호 사이의 숫자를 추출하려면 어떻게해야합니까?

더 일반적으로, 이러한 도구의 어떤 cut, sed, grep또는 awk그러한 작업에 적합한 것입니까?

답변:


16

GNU grep이 있다면 사용할 수 있습니다. -o 옵션을 하여 정규식을 검색하고 일치하는 부분 만 출력 . 다른 grep 구현은 전체 행만 표시 할 수 있습니다. 한 행에 여러 개의 일치 항목이있는 경우 별도의 행에 인쇄됩니다.

grep -o '\[[0-9]*\]'

대괄호가 아닌 숫자 만 원하면 조금 더 어려워집니다. 너비가 0 인 어설 션을 사용해야합니다. 빈 문자열과 일치하는 정규 표현식이지만 대괄호로 시작하거나 뒤에 오는 경우에만 가능합니다. 너비가 0 인 어설 션은 Perl 구문에서만 사용할 수 있습니다.

grep -P -o '(?<=\[)[0-9]*(?=\])'

sed를 사용하면로 인쇄를 끄고 -n전체 줄을 일치시키고 일치하는 부분 만 유지해야합니다. 한 줄에 여러 개의 가능한 일치 항목이 있으면 마지막 일치 항목 만 인쇄됩니다. sed 사용에 대한 자세한 내용 은 주변 문자인쇄하지 않고 'sed'와 일치하는 정규식 추출을 참조 하십시오.

sed -n 's/^.*\(\[[0-9]*\]\).*/\1/p'

또는 대괄호가 아닌 숫자 만 원하는 경우 :

sed -n 's/^.*\[\([0-9]*\)\].*/\1/p'

이 없으면 grep -o단순하고 이해하기 쉬운 것을 원한다면 Perl을 선택하는 것이 좋습니다. 모든 행 ( -n)에서 행에 대한 일치 항목이 있으면 \[[0-9]*\]해당 일치 항목 ( $&)과 줄 바꿈 ( -l) 을 인쇄하십시오 .

perl -l -ne '/\[[0-9]*\]/ and print $&'

숫자 만 원하면 정규식에 괄호를 묶어 그룹을 구분하고 해당 그룹 만 인쇄하십시오.

perl -l -ne '/\[([0-9]*)\]/ and print $1'

PS 대괄호 사이에 하나 이상의 숫자 만 필요 [0-9]*하면 [0-9][0-9]*으로 또는 [0-9]+펄로 변경하십시오.


그가 " 괄호 사이 의 숫자 추출하고 싶다"는 것 외에는 모든 것이 좋습니다 . 나는 "제외 [number]"는 다음을 제외하고 의미 한다고 생각합니다.[0-9]
Peter.O

1
@ Peter.OI는“[number]를 제외하고”해당 양식의 다른 부분이 없다는 것을 이해했습니다. 그러나 경우를 대비하여 숫자 만 인쇄하는 방법을 보여주기 위해 답변을 편집했습니다.
Gilles 'SO- 악한 중지'

1
perl정규식 주장은 정말 유용하게 보입니다! grep 에서조차도 앞뒤 어설 션을 모두 사용하는 것을 본 후에 그들에 대해 읽었습니다 (정규식 엔진을 선택할 수 있다는 사실로 전환했습니다). 나는 여기서부터 perl의 정규식에 조금 더 시간을 할애 할 것입니다. 감사합니다 ... PS .. 방금 읽었습니다 man grep. "이것은 매우 실험적이며 grep -P는 구현되지 않은 기능을 경고 할 수 있습니다." ... 그것이 불안정하지 않길 바래요 (?) ...
Peter.O

5

으로 할 수 없습니다 cut.

  1. tr -c -d '0123456789\012'
  2. sed 's/[^0-9]*//g'
  3. awk -F'[^0-9]+' '{ print $1$2$3 }'
  4. grep -o -E '[0-9]+'

tr 문제에 가장 자연스럽게 적합하며 아마도 가장 빨리 실행될 수 있지만 속도면에서 이러한 옵션을 분리하려면 거대한 입력이 필요하다고 생각합니다.


sed를 들어, ^.*욕심이고 모든하지만 마지막 숫자를 소모하며, +요구로 \+그렇지 않으면 POSIX를 사용 \([0-9][0-9]*\).... 그리고 어떤 경우에 's/[^0-9]*//g', 단지뿐만 아니라 작동 ... Thanks for the 그럴 -c` 예,하지만 후행되지 않도록 \012surperfluous?
Peter.O

@Peter 그것을 잡아 주셔서 감사합니다. 나는 sed 예제를 테스트했다고 맹세했을 것입니다. :( 귀하의 버전으로 변경했습니다. 관련 \012: 그렇지 않으면 줄 tr바꿈 이 필요할 것입니다.
Kyle Jones

아하 ... 내가로보고 있었다 \0, 1, 2(또는 \, 0, 1, 2). 8 진수로 보일 정도로 조율되지 않았습니다. 감사합니다.
Peter.O

4

당신은 숫자가 아닌 문자 사이의 연속적인 숫자의 집합을 추출 의미, 내가 생각 sed하고 awk(비록 최고grep 또한 당신에게 일치하는 문자를 제공 할 수 있습니다)

sed: 물론 숫자와 일치 할 수는 있지만 반대의 작업은 숫자가 아닌 숫자를 제거하는 것이 흥미로울 것입니다 (한 줄에 하나의 숫자 만있는 한 작동합니다).

$ echo nn3334nn | sed -e 's/[^[[:digit:]]]*//g'
3344

grep: 연속 숫자와 일치시킬 수 있습니다

$ echo nn3334nn | grep -o '[[:digit:]]*'
3344

나는 그것에 대한 awk경험이 없기 때문에 예를 들지 않는다 . sed스위스 칼 이지만 이 grep작업을 수행하는보다 간단하고 읽기 쉬운 방법을 제공합니다.이 방법은 각 입력 줄에서 둘 이상의 숫자에 대해서도 작동합니다 (입력 -o의 일치하는 부분 만 인쇄합니다) 자체 라인에서) :

$ echo dna42dna54dna | grep -o '[[:digit:]]*'
42
54

그냥 비교, 여기입니다 sed의 eqivalent "두 개 이상의 전화 번호 줄에"grep -o '[[:digit:]]*'. . . sed -nr '/[0-9]/{ s/^[^[0-9]*|[^0-9]*$//g; s/[^0-9]+/\n/g; p}'... (+1)
Peter.O

2

이것으로 할 수 없다고 말했기 때문에 cut, 나는 cut"최고의"로서의 사용을 보증하지는 않지만 다른 것보다 적어도 나쁘지 않은 솔루션을 만드는 것이 쉽게 가능하다는 것을 보여줄 것입니다. (또는 심지어 특히 좋은) 솔루션. 어떤 용액 특별히 보지 않고 있다고해야 *[하고 ]*가정을 단순화하게 자리 주위 및 실시 예에 아스카 의해 주어진 다음 중 하나 (예를 들어 숫자 외부보다 더 복잡하기 때문에, 고장이 경향 *[]*도시되지 않아야). 이 솔루션은 최소한 괄호를 확인하고 별표도 확인하도록 확장 할 수 있습니다 (독자의 연습으로 남음).

cut -f 2 -d '[' myfile.txt | cut -f 1 -d ']'

이것은 -d구분자를 지정하는 옵션을 사용합니다. 분명히 cut파일에서 읽는 대신 표현식 으로 파이프 할 수도 있습니다. 하지만 cut그것은 (아무 정규식 엔진) 간단하기 때문에, 꽤 빨리 아마, 당신은 그것을 호출이 두 번 이상 (또는 확인하기 위해 몇 시간에서 *) 일부 프로세스 오버 헤드를 만듭니다. 이 솔루션의 한 가지 장점은 특히 정규 표현식 구조에 정통하지 않은 일반 사용자의 경우 읽기 쉽다는 것입니다.

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