대신 특정 선의 패턴이

대신 특정 선의 패턴이

파일에서 여러 줄 패턴을 검색하는 방법을 찾고 있습니다.

예를 들어, 다음 숫자 목록이 입력 파일이라고 가정해 보겠습니다.

3
2
5
4
8
2
5
4
2
4
2
5
4

2-4행(포함)의 인스턴스를 검색하려는 경우 결과는 다음과 같습니다.

3

그 특정 줄이 반복되는 정확한 횟수이기 때문입니다. 또한 파일의 특정 라인 수와 라인 번호의 특정 범위를 처리할 수 있기를 원합니다.

답변1

당신이 사용할 수있는pcregrep, 대부분의 배포판에서 사용 가능합니다. 다음 명령은 고정 문자열과 일치합니다.

pcregrep -Mc '^2\n5\n4$' input.txt

설명하다

매뉴얼 페이지에서 pcregrep은 "Perl 호환 정규식을 사용한 grep"입니다.

  • -M:여러 줄 정규식 일치
  • -c: 일치 자체가 아닌 일치 개수(count)를 출력합니다.
  • ^2\n5\n4$: 각각 별도의 줄에 2, 5, 4에 대한 정규 표현식입니다.

대신 특정 선의 패턴이

질문의 후속 주석은 일치하는 패턴이 고정 문자열이 아니라 일반적인 "라인 2에서 라인 4"임을 시사합니다. 여기에서 명령 대체를 사용하여 입력 파일의 행을 구문 분석할 수 있습니다.

pcregrep -Mc "^\Q$(sed -n 2,4p input.txt)\E$" input.txt

설명하다

  • tail -n+2 input.txt: 출력 파일, 라인 2부터 시작
  • head -n3: 처음 3줄만 출력
  • \Q...\E:인용하다정규식 일치 대신 기본 문자열 일치 ...(명령의 출력에 해당 항목이 포함되어 있지 않다고 가정 \E).

replacement( ) sed ... input.txt명령이 제거되므로 출력의 마지막 몇 줄은 비어 있지 않다고 가정합니다.$(...)모두후행 개행 문자.

답변2

$ perl -l -0777pe '$_=()=/^2\n5\n4$/mg' input_file
3

피복재:

  • -0777=> 후루룩 소리 모드는 전체 파일을 읽는 것을 의미합니다.
  • -p => 다음 레코드를 읽기 전에 현재 레코드를 표준 출력으로 인쇄합니다 $_.
  • -l => RS 설정 = ORS = "\n"
  • 정규 표현식은 우리의 경우 전체 파일 /^2\n5\n4$/mg에 암시적으로 적용됩니다 . $_문자열의 시작과 문자열의 끝 외에도 정규식 수정자는 /m줄 끝과 시작도 일치해야 합니다. 수정자는 /g전체 파일에서 모든 일치 항목을 가져옵니다 .$_
  • 목록 컨텍스트에서 이 작업을 수행하고 이를 빈 목록에 할당합니다. 따라서 $_에는 목록의 요소 수, 즉 정규식이 실제로 일치하는 횟수가 다시 할당됩니다.

화타이

답변3

귀하의 게시물에는 정규식 지원에 대한 요구 사항이 언급되어 있지 않으므로 고정 리터럴 텍스트 문자열을 검색할 것이라고 가정합니다.

이것은 지금까지 본 것 중 가장 빠른 알고리즘은 아닐 수도 있지만 시간이 충분하다면 작동할 것입니다. 동일한 첫 번째 줄로 시작하고 동일한 SHA256 해시를 갖는 여러 N 라인 패턴이 있는 경우 잘못된 결과를 제공하는 작은 결함이 있습니다. 가능한 모든 N 라인 패턴에는 고유한 SHA256 해시가 있다고 가정합니다.

대용량 파일, 특히 패턴의 첫 번째 행이 많이 포함된 파일의 경우 속도가 매우 느릴 수 있습니다.

#!/usr/bin/env bash

# What's the name of the list file?
LIST=list

# What's the name of the pattern file?
PATTERN=pattern

# We'll figure out how many times the pattern lines appear (consecutively) in the list.

# Where's your SHA256 tool?
SHA256=/sbin/sha256

# what's the first line of pattern?
PATTERN_START="$(head -1 $PATTERN)"

# where in the list does that single line appear (what line numbers?)
START_LINES="$(grep -nx "$PATTERN_START" $LIST | sed -e 's/:.*//')"

# how many lines long is the pattern?
PAT_LEN="$(grep -c  ^ < $PATTERN)"

echo Pattern is $PAT_LEN lines long, and might start at any of these lines:
echo $START_LINES

PAT_HASH="$($SHA256 < "$PATTERN")"

# So how many times does $PATTERN appear consecutively in $LIST?
PAT_COUNT=0

for LINE in $START_LINES
do
        HASH="$(tail +$LINE $LIST | head -$PAT_LEN | $SHA256 -q)"
        if [ "$HASH" = "$PAT_HASH" ]
        then
                echo match at line $LINE
                PAT_COUNT=$(($PAT_COUNT+1))
        fi
done

echo The pattern was found $PAT_COUNT times

산출:

$ cat list
3
2
5
4
8
2
5
4
2
4
2
5
4
$ cat pattern
2
5
4
$ . foo.sh 
Pattern is 3 lines long, and might start at any of these lines:
2 6 9 11
match at line 2
match at line 6
match at line 11
The pattern was found 3 times

답변4

어때요?

a="2 5 4"; tr '\n' ' '  < test | grep -o "[^0-9]$a[^0-9]" | wc -l

원하는 구분 기호를 사용하세요.

22 5 44다음과 같은 경우 일치를 방지하려면 정규식이 필요합니다.

관련 정보