전체 줄이 필요하지 않고 정규 표현식과 일치


15

나는 단순히 정규 표현식에서 일치를 가져와야합니다.

$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"

출력은 괄호 안에 일치하는 것만 있어야합니다.

grep 이 전체 줄과 일치하므로 grep 을 사용할 수 있다고 생각하지 마십시오 .

이 작업을 수행하는 방법을 알려주십시오.

답변:


12

2 가지 :

  • @Rory에서 언급했듯이 -o옵션 이 필요 하므로 일치하는 항목 만 인쇄됩니다 (전체 줄 대신)
  • 또한 -PPerl 정규 표현식을 사용 하는 옵션이 필요합니다. Perl 정규 표현식에는 미리보기 (?= )뒤에 찾기 와 같은 유용한 요소가 포함되어 있습니다. 이러한 요소 (?<= )는 부품을 찾지 만 실제로는 일치하지는 않습니다.

Parensis 내부의 부분 만 일치 시키려면 다음을 수행하십시오.

grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt

파일에 sting이 포함되어 있으면 /(a)5667/grep은 다음과 같은 이유로 'a'를 인쇄합니다.

  • /(에 의해 발견 \/\(되지만 보고 뒤에 있기 때문에 (?<= )보고되지 않습니다.
  • a로 일치 \w하여 인쇄됩니다 (때문에 -o)
  • )5667/<B 발견 \).+\/,하지만 그들이에 있기 때문에 예견 (?= ) 그들은보고되지 않습니다

18

-o옵션을 사용하십시오 grep.

예 :

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar

4
좋은 슬픔 ... 당신은 내가 그것을 sed하기 위해 역 참조로 몇 번이나 씨름했는지 알고 있습니까?
Insyte

10
grep / egrep에 대한 o 옵션은 요청한대로 () 안에있는 것이 아니라 전체 정규 표현식과 일치하는 것만 반환합니다.
Kyle Brandt

1
그러나 그것은 어쨌든 알아야 할 아주 좋은 것입니다 :-)
Kyle Brandt

2
@KyleBrandt : 한 부분 만 (예 : 페 렌스) 일치 시키려면 나머지 부분을 미리 보거나 뒤에 보도록 할 수 있습니다 : (? <=) 및 (? =)
DrYak

6
    sed -n "s/^.*\(captureThis\).*$/\1/p"

-n      don't print lines
s       substitute
^.*     matches anything before the captureThis 
\( \)   capture everything between and assign it to \1 
.*$     matches anything after the captureThis 
\1      replace everything with captureThis 
p       print it

4

괄호 안에있는 항목 만 원하면 하위 일치 (명명 된 또는 캡처 된 캡처 그룹) 캡처를 지원하는 항목이 필요합니다. 나는 grep이나 egrep이 이것을 할 수 있다고 생각하지 않는다. perl과 sed는 할 수있다. 예를 들어, perl을 사용하면 :

foo라는 파일에 다음과 같은 줄이있는 경우 :

/adsdds      /

그리고 당신은 :

perl -nle 'print $1 if /\/(\w).+\//' foo

문자 a가 반환됩니다. 그것은 당신이 원하는 것이 아닐 수도 있습니다. 일치시키려는 내용을 알려 주면 더 나은 도움을받을 수 있습니다. $ 1은 첫 번째 괄호 세트에서 캡처 한 것입니다. 두 번째 세트는 $ 2입니다.


방금 괄호 안에있는 것을 일치 시키려고했습니다. 펄이나 PHP 스크립트로 전달하는 것이 답이 될 수 있습니다.
Alex L

4

shell 외에도 bash 로 질문에 태그를 지정했기 때문에 grep 외에 다른 해결책이 있습니다 .

Bash에는 =~Perl과 마찬가지로 연산자를 사용하여 버전 3.0부터 자체 정규식 엔진이 있습니다.

이제 다음 코드가 주어집니다.

#!/bin/bash
DATA="test <Lane>8</Lane>"

if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
        echo $BASH_REMATCH
        echo ${BASH_REMATCH[1]}
fi
  • 모든 확장을 얻기 위해서가 bash아니라 그대로 호출해야 sh합니다.
  • $BASH_REMATCH 전체 정규 표현식과 일치하는 전체 문자열을 제공하므로 <Lane>8</Lane>
  • ${BASH_REMATCH[1]} 첫 번째 그룹과 일치하는 부분을 제공하므로 8

@DrYak님께, 정규식으로 XML을 파싱하지 않기를 바랍니다. : :)
joonas.fi

더 나빠요 SANSparallel 고속 대규모 정렬 소프트웨어에 >의해 분출 된 XML과 FASTA 데이터 (모두 완전히 다른 목적으로 기호를 사용함)의 끔찍한 혼합을 분석하고 있습니다. 물론 두 형식 모두 이스케이프없이 인터레이스됩니다. 따라서 표준 XML 라이브러리를 던질 수는 없습니다. 그리고 나는 코드 의이 시점에서 Bash 정규 표현식을 사용하고 있습니다. 왜냐하면 두 개의 데이터 만 추출하면되므로 2 정규 표현식 이이 혼란에 대한 전용 파서를 작성하는 것보다 훨씬 더 잘 작동합니다. #LifeInBioinformatics
DrYak

즉 : 1 하나 개의 숫자가 전체 XML 탱고 춤보다 정규식 rathan와 함께 할 간단 추출하는 지점이있다
DrYak

아야! :)
joonas.fi

2

파일에 다음이 포함되어 있다고 가정합니다.

$ cat file
Text-here>xyz</more text

그리고 당신은 문자 (들) 사이의 원하는 ></, 당신이 중 하나를 사용할 수 있습니다 :

grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
perl -nle 'print $1 if />(\w+)<\//' file

모두 문자열 "xyz"를 인쇄합니다.

이 줄의 숫자를 캡처하려면 다음을 수행하십시오.

$ cat file
Text-<here>1234</text>-ends

grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
perl -nle 'print $1 if />([0-9]+)<\//' file


나에게 중요한 것은 \ d가 sed와 함께 작동하지 않는다는 것을 깨닫는 것이었다. 거기에 [0-9] +를 사용하는 이유가 있습니다. :)
user27432

@ user27423 그렇지는 않지만 POSIX 문자 클래스 (고독한 읽기 , 즐거운 읽기 )는 다음을 수행 echo 'Text-<here>1234</text>-ends' | sed -E 's|.*>([[:digit:]]+)<.*|\1|'합니다. 일부의 경우 (예에서 [0-9][[:digit:]]) 그들은 다른 사람 I (예 : 그들이 생각하지 도움말 가독성을 할 [ \t\n\r\f\v][:space:]).
사무엘 하머

0

이것은 당신이 요구하는 것을 성취 할 것이지만, 그것이 당신이 정말로 원하는 것이라고 생각하지 않습니다. 나는 .*정규식 앞에를 넣어 일치하기 전에 아무것도 먹지 만 욕심 많은 조작이므로 \w문자열 의 두 번째 문자 만 일치 합니다.

parens 및을 이스케이프해야합니다 +.

sed 's/.*\(\w\).\+/\1/' myfile.txt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.