2009-11-14 7 views
87

sed, awk 또는 gawk를 사용하여 검색 - 바꾸기와 같은 작업을 수행하는 방법에 대한 예제와 맨 페이지가 많이 있습니다.일치하는 것만 인쇄하려면 sed, awk 또는 gawk를 사용하는 방법은 무엇입니까?

하지만 제 경우에는 특정 값을 추출하기 위해 텍스트 파일에 대해 실행하고 싶은 정규식이 있습니다. 나는 수색과 교체를하고 싶지 않다. 이것은 bash로부터 호출되고 있습니다. 이 소리

a 
b 
c 
abc12345xyz 
a 
b 
c 

으로 간단하게, 내가 SED/AWK/둔한 제대로 호출하는 방법을 알아낼 수 없습니다 :

예 정규 표현식 :

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

예 입력 파일 예를 들어 보겠습니다 . 내가 기대하고 있었는지, 내 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 
+5

와우 ... 사람들이이 질문을 -1 개 투표 했습니까? 정말로 그 질문에 부적당한가? –

+0

Regex와 sed/awk 또는 vi, emacs 또는 teco와 같은 편집기와 같은 강력한 명령 줄 유틸리티를 사용하는 것이 완벽하게 적합한 것처럼 보입니다. 단지 일부 ol 응용 프로그램을 사용하는 것보다 더 프로그래밍 할 수 있습니다. IMO 이것은 SU에 속합니다. – Dereleased

+0

처음 형태에서 요구 사항 중 일부를 명확하게 정의하지 않았기 때문에 아마도 투표에서 제외되었습니다. 당신이 답에 OP의 코멘트를 읽지 않는다면 (내가 배 모양으로 갈 때 삭제 한 것을 포함해서), 그것은 여전히 ​​않습니다. – pavium

답변

38

sed (맥 OS X) + 작동하지 않았다 예를 들어, 당신은 항상 시작과 끝에서 0 개 이상의 비 수치 묻혀 하나의 숫자가 있다면.내가 대신 *을 시도하고 나는 인쇄 일치 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 
+0

고맙습니다. + 대신 + 대신 *를 사용하면이 기능이 저 또한 효과가있었습니다. –

+2

... 그리고 "p"옵션을 사용하면 일치 여부를 알 수 없었습니다. 다시 한번 감사드립니다. –

+2

나는'+'를 벗어나서 나를 위해 일했다.'sed -n 's /^.* abc \ ([0-9] \ + \) xyz. * $/\ 1/p'' –

15

는 내 자신이 쉽게 만들 perl를 사용합니다. 예 :

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

이 펄을 실행

-n 옵션은 STDIN에서 한 번에 한 줄 읽고 코드를 실행하기 위해 펄을 지시합니다. -e 옵션은 실행할 명령어를 지정합니다.

명령어는 읽은 행에 대해 정규 표현식을 실행하고 일치하는 경우 첫 번째 대괄호 집합 ($1)의 내용을 인쇄합니다.

마지막으로 여러 개의 파일 이름을 사용할 수 있습니다. 예 : 그런 다음 비트를 제거 선을 선택합니다

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

+0

고마워,하지만 우리는 펄에 접근 할 수 없다. 그래서 나는 sed/awk/gawk에 대해 물어 보았다. –

1

원하지 않는 :

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> 

업데이트 : 당신이 실제 상황이 더 복잡한 경우 나 수정에 분명히, 입술이 필요합니다.

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

흥미 롭습니다 ... 그래서 복잡한 정규 표현식을 적용하고 (...) 섹션에있는 것을 되돌릴 수있는 간단한 방법이 없습니까? 왜냐하면 당신이 greed로 sed로 무엇을했는지를 알기는하지만 실제 상황은 "abc"와 "xyz"를 삭제하는 것보다 훨씬 더 복잡합니다. 추출하려는 텍스트의 양쪽에 많은 텍스트가 나타날 수 있기 때문에 정규식이 사용됩니다. –

+0

RE가 정말 복잡하면 * 더 좋은 방법이라고 확신합니다. 아마도 몇 가지 예나 더 자세한 설명을 제공 한 경우 답변을 조정할 수 있습니다. – paxdiablo

-3

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

/.*abc([0-9]+)xyz.*/ { 
      print $0; 
      next; 
      } 
      { 
      /* default, do nothing */ 
      } 
+0

의 마지막 단락을 확인하십시오. grep과 같은 동작을합니다 ... – dmckee

+0

숫자 값'([0-9 +])'를 출력하지 않습니다. 이것은 전체 행을 출력합니다. –

-3
gawk '/.*abc([0-9]+)xyz.*/' file 
+2

이것은 효과가없는 것 같습니다. 그것은 매치 대신 전체 라인을 출력합니다. 샘플 입력 파일에 –

+0

이 있으면 해당 패턴이 전체 행입니다. 권리??? 패턴이 특정 필드에 있음을 알고 있다면 $ 1, $ 2 등을 사용하십시오. 예를 들어 gawk '$ 1 ~ /.*abc([0-9]+)xyz.*/'file – ghostdog74

5

: 나는 다음과 같은 스크립트를 사용합니다.

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

.../나머지 라인의 경우, 자리 건너 뛰고 삭제하는 제거 모든 선행 및 후행 숫자가 아닌 문자 : 여기에 최고의 sed 아니에요 경우

내가 가지고 올 수있다 . (나는 당신의 의도가 하나를 포함하고있는 각 줄에서 번호를 추출하는 것이라고 짐작한다.)

같은의 문제 :.

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

이 ... sed 만 지원한다는 것입니다 "욕심"일치 ... 그래서 처음 * 것이다 나머지 줄과 일치해라. 부정한 문자 클래스를 사용하여 비 욕심 많은 일치를 얻거나 ... 또는 sed의 버전을 Perl 호환 또는 다른 정규 표현식으로 확장 할 수 없다면 패턴 공간에서 정확한 패턴 일치를 추출 할 수 없습니다 (a 선).

+0

당신은'sed' 명령 중 두 가지를'sed -n's/[^ 0-9] * \ ([0-9] \ + \). */\ 1/p'' –

+0

이전에는 grep에서 -o 옵션에 대해 알지 못했습니다. 잘 알고 있습니다. 하지만 "(...)"가 아닌 전체 경기를 인쇄합니다. 따라서 "abc ([[: digit :]] +) xyz"와 일치하는 경우에는 "abc"및 "xyz"와 숫자를 얻을 수 있습니다. –

-1

다음, 둔한 및 구성 요소를 사용하는 유일한 방법은 당신이

while read -r line 
do 
    case "$line" in 
     *abc*[0-9]*xyz*) 
      t="${line##abc}" 
      echo "num is ${t%%xyz}";; 
    esac 
done <"file" 
2

펄이 깨끗한 구문 쉘와 함께 할 수 있지만 펄이없는 경우 (항상 존재를 이해) 정규 표현식의 gensub 기능을 사용하는 것입니다. [(gensub합니다 (// 사이) 전체 정규 표현식을 대체, 그래서 당신이를 넣어야 * 이전과 이후 :. 샘플 입력 파일의

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

출력은

12345 

참고가 될 것입니다 0-9] +)를 사용하여 대체 문자의 앞뒤에있는 텍스트를 제거 할 수 있습니다.

+2

gawk를 사용해야하는 경우 (또는 사용하고 싶은 경우) 영리하고 실행 가능한 솔루션입니다. 분명히 밝히지 만, GNU가 아닌 awk에는 gensub()이 없으므로 이것을 지원하지 않습니다. – cincodenada

+0

니스! 그러나 캡처 된 그룹에 액세스하려면'match() '를 사용하는 것이 가장 좋습니다. 이에 대해서는 [내 대답] (http://stackoverflow.com/a/39075261/1983854)을 참조하십시오. – fedorqui

28

sed -rn 's/.*abc([0-9]+)xyz.*/\1/gp' 
  • -n이가 그렇게 당신이 캡처 그룹 ()을 괄호 탈출하지 않아도 만드는 결과 라인
  • -r를 인쇄하지 않습니다 할 sed를 사용할 수 있습니다.
  • \1
  • 캡처 그룹 일치
  • /g 글로벌 경기
  • /p 인쇄 결과

나는이 쉽게

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

지금까지 가장 잘 설명 된 답변입니다. –

+0

몇 가지 설명을 드리면 문제가 무엇인지 잘못 이해하는 것이 좋습니다. 고맙습니다 ! – r4phG

3

당신은 match()awk을 사용할 수 있습니다 그 자신을위한 tool을 썼다 캡처 된 그룹에 액세스하려면 :

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

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


grep하면 뒤에 봐 -를 사용하고 예견 할 수는 abcxyz 내에서 발생하고 단지 숫자를 인쇄 할 때

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

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

이 패턴 [0-9]+을 확인합니다.

관련 문제