![같은 줄에서 패턴이 나타나는 횟수를 계산합니다.](https://linux55.com/image/150289/%EA%B0%99%EC%9D%80%20%EC%A4%84%EC%97%90%EC%84%9C%20%ED%8C%A8%ED%84%B4%EC%9D%B4%20%EB%82%98%ED%83%80%EB%82%98%EB%8A%94%20%ED%9A%9F%EC%88%98%EB%A5%BC%20%EA%B3%84%EC%82%B0%ED%95%A9%EB%8B%88%EB%8B%A4..png)
이 문제는 쉘 스크립트에서 해결해야 합니다. 아래 문자열의 발생 횟수를 세고 있는데 abc
제가 원하는 답은 3입니다.
echo abcsdabcsdabc | grep -o abc
abc
abc
abc
-o
옵션이 없다고 가정하면 grep
어떻게 처리해야 할까요?
답변1
문자열은 다음으로 구분된 필드로 구성되어 있다고 생각하세요 abc
.
$ echo abcsdabcsdabc | awk -F 'abc' '{ print (length > 0 ? NF - 1 : 0) }'
3
구분 기호 발생 횟수는 abc
1에서 구분 기호가 구분하는 필드 수를 뺀 값입니다.
$ echo abcsdabcsdabc | awk '{ n=0; while (sub("abc", "xxx")) n++; print n }'
3
abc
그러면 해당 줄의 하위 문자열이 대체되고 xxx
완료된 횟수를 계산한 다음 해당 숫자를 출력합니다. n=0
입력 줄이 한 줄뿐인 경우에는 필요하지 않습니다.
gsub()
의 함수는 awk
대체 횟수를 반환하므로 위의 내용은 다음과 같이 단순화될 수 있습니다.
$ echo abcsdabcsdabc | awk '{ print gsub("abc", "xxx") }'
3
에서는 bash
이 프로그램에서 수행하는 것과 동일한 작업을 수행할 수 있습니다.awk
sub()
string=abcsdabcsdabc
n=0
while [[ $string == *abc* ]]; do
n=$(( n+1 ))
string=${string/abc/xxx} # replace first occurrence of "abc" with "xxx"
done
printf '%d\n' "$n"
while
이는 위의 두 번째 프로그램과 마찬가지로 in이 더 이상 발견되지 않을 때까지 루프를 사용하여 in 값의 하위 문자열을 대체합니다 .abc
$string
xxx
abc
$string
awk
답변2
그리고 awk
:
awk -- 'BEGIN{print gsub(ARGV[2], "&", ARGV[1])}' abcsdabcsdabc abc
패턴(여기서)은 확장 정규식( /supported 정규식 과 유사) abc
으로 처리됩니다 .awk
grep -E
egrep
이 구문을 사용하면 주제와 정규 표현식에 여러 줄을 포함할 수 있습니다. 우리도 피한다echo
임의 데이터를 내보낼 수 없는 경우에 대해 자주 묻는 질문.
perl
정규식을 사용하세요 (GNU와 유사 grep -P
):
perl -le 'print scalar (() = $ARGV[0] =~ m{$ARGV[1]}g)' -- abcsdabcsdabc abc
(그러나 로케일의 인코딩에 따라 인수는 텍스트로 해석되지 않습니다. 예를 들어 UTF-8 로케일에서 é
및 .
인수를 사용하면 1(문자) 대신 2(바이트)가 보고됩니다.
를 사용하면 zsh
다음을 수행할 수 있습니다.
occurrences() {
set -o localoptions -o extendedglob
local n=0
: ${1//(#m)$2/$((++n))}
echo $n
}
occurrences abcsdabcsdabc abc
여기서 두 번째 인수( abc
)는 고정 문자열로 해석됩니다. 대신 $2
확장 $~2
된 zsh glob 패턴(확장 정규식보다 더 광범위한 기능 세트를 갖지만 구문은 다름)으로 해석됩니다.
답변3
Raku(이전 Perl_6) 사용
~$ echo "abcsdabcsdabc" | raku -ne '.match("abc", :global).say;'
(「abc」 「abc」 「abc」)
일치 항목은 위에 나와 있습니다(한 줄씩). 일치하는 항목 수(한 줄씩)는 다음과 같습니다.
~$ echo "abcsdabcsdabc" | raku -ne '.match("abc", :global).elems.say;'
3
참고: :global
매개변수는 로 축약될 수 있습니다 :g
.
HTH.
답변4
GNU 사용sed
echo abcsdabcsdabc | sed 's/abc/abc\n/g' | wc -w