[regex] sed, awk 또는 gawk를 사용하여 일치하는 항목 만 인쇄하는 방법은 무엇입니까?

sed, awk 또는 gawk를 사용하여 검색 및 바꾸기와 같은 작업을 수행하는 방법에 대한 많은 예제와 매뉴얼 페이지를 봅니다.

하지만 제 경우에는 특정 값을 추출하기 위해 텍스트 파일에 대해 실행하려는 정규식이 있습니다. 검색 및 바꾸기를 원하지 않습니다. 이것은 bash에서 호출됩니다. 예를 들어 보겠습니다.

정규 표현식의 예 :

.*abc([0-9]+)xyz.*

입력 파일 예 :

a
b
c
abc12345xyz
a
b
c

간단하게 들리지만 sed / awk / gawk를 올바르게 호출하는 방법을 알 수 없습니다. 내가 원하는 것은 bash 스크립트 내에서 다음과 같습니다.

myvalue=$( sed <...something...> input.txt )

내가 시도한 것은 다음과 같습니다.

sed -e 's/.*([0-9]).*/\\1/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\\1/g' example.txt # extracts nothing



답변

sed(Mac OS X)가 +. *대신 시도 하고 p인쇄 일치 태그를 추가했습니다 .

sed -n 's/^.*abc\([0-9]*\)xyz.*$/\1/p' example.txt

없이 하나 이상의 숫자를 일치 시키 +려면 다음을 사용합니다.

sed -n 's/^.*abc\([0-9][0-9]*\)xyz.*$/\1/p' example.txt


답변

sed를 사용하여이 작업을 수행 할 수 있습니다.

 sed -rn 's/.*abc([0-9]+)xyz.*/\1/gp'
  • -n 결과 라인을 인쇄하지 마십시오
  • -r이렇게하면 캡처 그룹 괄호를 탈출 할 수 없습니다 ().
  • \1 포획 그룹 경기
  • /g 글로벌 경기
  • /p 결과를 인쇄

이 작업을 더 쉽게 만들어주는 도구 를 직접 작성했습니다.

rip 'abc(\d+)xyz' '$1'


답변

나는 perl이것을 더 쉽게 만들기 위해 사용 합니다. 예 :

perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/'

이것은 Perl을 실행하고이 -n옵션은 Perl이 STDIN에서 한 번에 한 줄씩 읽고 코드를 실행하도록 지시합니다. 이 -e옵션은 실행할 명령을 지정합니다.

이 명령어는 read 행에서 regexp를 실행하고 일치하는 경우 첫 번째 중괄호 ( $1) 세트의 내용을 인쇄합니다 .

당신은 또한 끝에 여러 파일 이름을 할 수 있습니다. 예 :

perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/' example1.txt example2.txt


답변

버전 경우 grep지원을 당신이 사용할 수있는 -o인쇄 옵션을 단지 당신의 정규 표현식 일치하는 모든 라인의 일부를.

그렇지 않다면 여기에 sed내가 생각 해낼 수 있는 최선의 방법이 있습니다 .

sed -e '/[0-9]/!d' -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'

… 숫자없이 삭제 / 건너 뛰고 나머지 행의 경우 모든 선행 및 후행 숫자가 아닌 문자를 제거합니다. (나는 당신의 의도가 하나를 포함하는 각 줄에서 숫자를 추출하는 것이라고 추측하고 있습니다).

다음과 같은 문제 :

sed -e 's/.*\([0-9]*\).*/&/' 

…. 또는

sed -e 's/.*\([0-9]*\).*/\1/'

sed“욕심 많은”일치 만 지원하므로 첫 번째. *가 나머지 줄과 일치합니다. 부정한 문자 클래스를 사용하여 탐욕스럽지 않은 일치를 달성하거나 sedPerl과 호환되는 버전 또는 정규식에 대한 다른 확장을 사용하지 않는 한 패턴 공간 (줄)에서 정확한 패턴 일치를 추출 할 수 없습니다. ).


답변

awkwith match()를 사용하여 캡처 된 그룹에 액세스 할 수 있습니다 .

$ awk 'match($0, /abc([0-9]+)xyz/, matches) {print matches[1]}' file
12345

이것은 패턴을 일치 시키려고합니다 abc[0-9]+xyz. 그렇게하면 matches첫 번째 항목이 block 인 array에 슬라이스를 저장합니다 [0-9]+. match() 해당 하위 문자열이 시작되는 문자 위치 또는 인덱스를 반환 하므로 (문자열의 시작 부분에서 시작하는 경우 1)print 작업을 트리거합니다 .


으로 grep당신은 모양 숨김 및보기 미리 사용할 수 있습니다 :

$ grep -oP '(?<=abc)[0-9]+(?=xyz)' file
12345

$ grep -oP 'abc\K[0-9]+(?=xyz)' file
12345

이 체크 패턴 [0-9]+이 내에서 발생 abc하고 xyz그냥 숫자를 인쇄합니다.


답변

perl은 가장 깨끗한 구문이지만 perl이 없으면 (항상 그런 것은 아닙니다) 정규식의 gawk와 구성 요소를 사용하는 유일한 방법은 gensub 기능을 사용하는 것입니다.

gawk '/abc[0-9]+xyz/ { print gensub(/.*([0-9]+).*/,"\\1","g"); }' < file

샘플 입력 파일의 출력은

12345

참고 : gensub는 전체 정규식 (// 사이)을 대체하므로 대체에서 숫자 앞뒤의 텍스트를 제거하려면 ([0-9] +) 앞뒤에. *를 넣어야합니다.


답변

라인을 선택하려면 원하지 않는 비트를 제거하십시오.

egrep 'abc[0-9]+xyz' inputFile | sed -e 's/^.*abc//' -e 's/xyz.*$//'

기본적으로 원하는 줄을 egrep선택한 다음 sed숫자 앞뒤의 비트를 제거하는 데 사용 합니다.

여기에서 실제로 작동하는 것을 볼 수 있습니다.

pax> echo 'a
b
c
abc12345xyz
a
b
c' | egrep 'abc[0-9]+xyz' | sed -e 's/^.*abc//' -e 's/xyz.*$//'
12345
pax> 

업데이트 : 분명히 실제 상황이 더 복잡하다면 RE를 수정해야합니다. 예를 들어 시작과 끝에서 항상 0 개 이상의 비 숫자 내에 단일 숫자가 묻혀있는 경우 :

egrep '[^0-9]*[0-9]+[^0-9]*$' inputFile | sed -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'