Grep은 어간을 찾아 단어만 인쇄합니다(줄은 제외).

Grep은 어간을 찾아 단어만 인쇄합니다(줄은 제외).

정규식을 통해 찾은 일치하는 단어만 인쇄하려고 합니다. 아래에서는 OPENSSL_NO_*소스 코드에 모든 옵션이 표시되기를 원합니다 .

$ grep -IR OPENSSL_NO
fuzz/asn1.c:#ifndef OPENSSL_NO_RFC3779
fuzz/asn1.c:#ifndef OPENSSL_NO_RFC3779
fuzz/asn1.c:#ifndef OPENSSL_NO_CMS
fuzz/asn1.c:#ifndef OPENSSL_NO_DH
fuzz/asn1.c:#ifndef OPENSSL_NO_EC
fuzz/asn1.c:#ifndef OPENSSL_NO_RFC3779
fuzz/asn1.c:#ifndef OPENSSL_NO_OCSP
fuzz/asn1.c:#ifndef OPENSSL_NO_TS
fuzz/asn1.c:#ifndef OPENSSL_NO_DH
fuzz/asn1.c:#ifndef OPENSSL_NO_DSA
...

완전한 단어만 인쇄하여 출력을 자르려고 하면 다음과 같습니다.

$ grep -oIR "OPENSSL_NO*"
fuzz/asn1.c:OPENSSL_NO
fuzz/asn1.c:OPENSSL_NO
fuzz/asn1.c:OPENSSL_NO
fuzz/asn1.c:OPENSSL_NO
fuzz/asn1.c:OPENSSL_NO
...

awk를 시도하면 전체 줄이 인쇄됩니다.

$ grep -IR OPENSSL_NO | awk '/OPENSSL_NO[_A-Z0-9_]/{ print $0 }'
fuzz/asn1.c:#ifndef OPENSSL_NO_RFC3779
fuzz/asn1.c:#ifndef OPENSSL_NO_RFC3779
fuzz/asn1.c:#ifndef OPENSSL_NO_CMS
fuzz/asn1.c:#ifndef OPENSSL_NO_DH
fuzz/asn1.c:#ifndef OPENSSL_NO_EC
...

그리고:

$ grep -IR OPENSSL_NO | awk '/\<OPENSSL_NO\>'
awk: line 1: runaway regular expression /\<OPENSSL_ ...

그리고:

$ grep -Eo -IR 'OPENSSL_NO_[A-Z0-9_]'
fuzz/asn1.c:OPENSSL_NO_R
fuzz/asn1.c:OPENSSL_NO_R
fuzz/asn1.c:OPENSSL_NO_C
fuzz/asn1.c:OPENSSL_NO_D
fuzz/asn1.c:OPENSSL_NO_E

그리고:

$ grep -IR OPENSSL_NO | sed -n 's/.*\(OPENSSL_NO\).*/\1/p'
OPENSSL_NO
OPENSSL_NO
OPENSSL_NO
OPENSSL_NO
OPENSSL_NO
...

단어를 일치시킨 다음 해당 단어만 인쇄하는 방법은 무엇입니까?


질문이 너무 많다는 점을 고려하면 이는 분명 고통스러운 작업입니다. 다음은 [단순? ] 질문에 대한 다양한 질문:

답변1

*정규식은 무엇을 의미하나요?0개 이상의 선행 원자. *쉘 와일드카드 연산자 와 혼동하고 있습니다 .0자 이상.

OPENSSL_NO_*OPENSSL_NO뒤에 0개 이상의 밑줄이 있음 을 나타냅니다 .

당신이 원하는 것:

grep -o 'OPENSSL_NO_.*'

.단일 문자와 일치하는 정규식 연산자는 어디에 있습니까?

또는:

grep -o 'OPENSSL_NO_[[:alnum:]]*'

0개 이상의 영숫자 문자(로캘에서 지원하는 모든 알파벳 스크립트)

확장하다정규 표현식(예: grep -E)에도 다음이 있습니다 +.1개 이상의 선행 원자. 그리고기초적인대신 정규식(-E 제외)을 사용할 수 있습니다 \{1,\}.

일부 구현에는 이러한 의미 grep도 있습니다 .\w영숫자 또는 밑줄그러나 일부 구현의 일부 버전에서는 이것으로 제한됩니다 A-Za-z0-9.

어쨌든 -o/는 -R표준 옵션이 아니라는 점에 유의하십시오. POSIXly에서는 다음을 수행할 수 있습니다.

sed -n 's/.*\(OPENSSL_NO_[[:alnum:]_]\{1,\}\).*/\1/p' < file

(한 줄에 한 번만 발생할 수 있으며, 여러 번 발생할 경우 가장 오른쪽에 있는 항목만 표시됩니다.)

파일 이름은 인쇄되지 않습니다. 이렇게 하려면 다음을 사용할 수 있습니다 awk.

find . -name '*.[hc]' -type f -exec awk 'match($0, /OPENSSL_NO_[[:alnum:]_]+/) {
  print FILENAME": "substr($0, RSTART, RLENGTH)}' {} +

답변2

정규식의 연산자는 *"0개 이상"을 의미하므로 grep은 "0"개의 추가 문자를 사용하여 해당 조건을 만족시킵니다.

grep이 나머지 용어를 포함하도록 어떤 방식으로든 정규식을 확장하겠습니다.

grep -o 'OPENSSL_NO_.*$' input

또는

grep -o 'OPENSSL_NO_.*\b' input

(두 경우 모두 밑줄을 추가했습니다.)

답변3

나는 같은 것을 달성하기 위해 awk 명령을 사용했습니다

for i in {1..2}; do awk -v i="$i" '$i ~/^OPENSSL/ {print $i}' example.txt; done

산출

OPENSSL_NO_RFC3779
OPENSSL_NO_RFC3779
OPENSSL_NO_CMS
OPENSSL_NO_DH
OPENSSL_NO_EC
OPENSSL_NO_RFC3779
OPENSSL_NO_OCSP
OPENSSL_NO_TS
OPENSSL_NO_DH
OPENSSL_NO_DSA

관련 정보