grep을 사용하여 총 발생 수 계산


215

grep -c파일에서 문자열이 몇 번이나 발생하는지 찾는 데 유용하지만 한 줄에 한 번만 발생합니다. 한 줄에 여러 번 발생하는 횟수를 계산하는 방법은 무엇입니까?

나는 다음보다 더 우아한 것을 찾고 있습니다.

perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'

4
나는 grep지정되었지만 알고 있는 사람에게는 ack답은 간단 ack -ch <pattern>합니다.
— Kyle Strand

답변:


302

grep -o은 라인을 무시하고 경기 만 출력합니다. wc그들을 셀 수 있습니다 :

grep -o 'needle' file | wc -l

'니들'또는 '멀티 니들'과도 일치합니다.
한 마디 만 :

grep -o '\bneedle\B' file | wc -l
# or:
grep -o '\<needle\>' file | wc -l

6
여기에는 GNU grep (Linux, Cygwin, FreeBSD, OSX)이 필요합니다.
— Gilles

@wag 어떤 마법을 않습니다 \b및 \B여기에서?
— Geek

6
@Geek \ b는 단어 경계와 일치하고 \ B는 단어 경계와 일치하지 않습니다. 위의 대답은 양쪽 끝에 \ b를 사용하면 더 정확합니다.
— Liam

1
줄당 발생 횟수를 보려면 grep -n 옵션 및 uniq -c ... grep -no '\ <needle \>'파일 | uniq -c
— jameswarren

@jameswarren uniq은 인접한 동일한 줄만 제거하므로 중복 항목이 항상 즉시 인접하는지 확실하지 않은 경우 sort급지하기 전에 공급 해야합니다 uniq.
— tripleee

16

당신이 (항상 가끔 다른 곳에서 리눅스와 Cygwin에서에) GNU의 GREP이있는 경우, 당신은 할 수 의 출력 라인을 계산grep -o : grep -o needle | wc -l.

Perl을 사용하면 다음보다 더 우아하게 찾을 수있는 몇 가지 방법이 있습니다 ( 고정 된 후에도 ).

perl -lne 'END {print $c} map ++$c, /needle/g'
perl -lne 'END {print $c} $c += s/needle//g'
perl -lne 'END {print $c} ++$c while /needle/g'

POSIX 도구 만 사용하는 경우 가능한 한 방법은 입력을 grep에 전달하기 전에 단일 일치로 입력을 분할하는 것입니다. 예를 들어 전체 단어를 찾으려면 먼저 단어가 아닌 모든 문자를 줄 바꿈으로 바꾸십시오.

# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'

그렇지 않으면이 특정 비트의 텍스트 처리를 수행하는 표준 명령이 없으므로 sed (마조히스트 인 경우) 또는 awk로 전환해야합니다.

awk '{while (match($0, /set/)) {++c; $0=substr($0, RSTART+RLENGTH)}}
     END {print c}'
sed -n -e 's/set/\n&\n/g' -e 's/^/\n/' -e 's/$/\n/' \
       -e 's/\n[^\n]*\n/\n/g' -e 's/^\n//' -e 's/\n$//' \
       -e '/./p' | wc -l

다음은 sedand를 사용하는 더 간단한 솔루션 grep입니다. 문자열이나 심지어는 정규 표현식에도 작동하지만 앵커 패턴이있는 몇 가지 모퉁이에서는 실패합니다 (예 : ^needle또는 \bneedle에서 두 번 발생 needleneedle).

sed 's/needle/\n&\n/g' | grep -cx 'needle'

위의 sed 대체 \n에서 줄 바꿈을 의미했습니다. 이것은 패턴 부분의 표준이지만 대체 텍스트에서는 이식성을 위해 backslash-newline을 대체합니다 \n.


4

나처럼 실제로 "둘 다; 정확히 한 번" (이것은 실제로 "둘 중 하나")을 원한다면 간단합니다.

grep -E "thing1|thing2" -c

출력을 확인하십시오 2.

이 방법의 장점은 (정확히 한 번만 경우 입니다 당신이 원하는) 쉽게 확장 할 것입니다.


실제로 한 번만 나타나는지 확실하지 않습니까? 당신이 찾고있는 것은 그 단어 중 하나가 적어도 한 번 존재한다는 것입니다.
— Steve Gore

3

awk needle를 필드 분리 자로 사용하는 또 다른 솔루션 :

awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'

일치 needle하고 구두점 을 찾으려면 필드 구분 기호를 적절하게 변경하십시오.

awk -F'^needle[ ,.?]|[ ,.?]needle[ ,.?]|[ ,.?]needle$' '{c+=NF-1}END{print c}'

또는 class : [^[:alnum:]]를 사용하여 모든 비 알파 문자를 포함하십시오.


정규 표현식 필드 구분 기호 (GNU awk 등)를 지원하는 awk가 필요합니다.
— Gilles

1

귀하의 예제는 파일의 총계가 아닌 한 줄당 발생 횟수 만 인쇄합니다. 이것이 원하는 경우 다음과 같이 작동 할 수 있습니다.

perl -nle '$c+=scalar(()=m/needle/g);END{print $c}' 

당신이 옳습니다-나의 예제는 첫 번째 줄에서 발생하는 횟수 만 계산합니다.

1

이것은 내 순수한 bash 솔루션입니다

#!/bin/bash

B=$(for i in $(cat /tmp/a | sort -u); do
echo "$(grep $i /tmp/a | wc -l) $i"
done)

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