Grep은 $MIDDLE에 일치하는 항목이 포함된 $START부터 $END까지의 행 세트를 찾습니다.

Grep은 $MIDDLE에 일치하는 항목이 포함된 $START부터 $END까지의 행 세트를 찾습니다.

Grep/Awk/Sed는 "0010|"에서 "0070|"까지의 행 집합을 찾고 $PH_NO에 일치 항목을 포함합니다.

아래는 샘플 데이터입니다. 0012 필드에 나타나는 전화번호와 해당 전체 고객 기록(0010에서 0070까지의 행)을 찾으려면 grep이 필요합니다. 데이터 파일에는 동일한 전화번호를 가진 2~3개의 고객 기록이 포함될 수 있으며 이를 모두 가져와야 합니다.

0010|Kumar||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|RAM||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 333| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|Joe||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|

참고: 저는 ksh와 함께 AIX 서버를 사용하고 있습니다.

답변1

그러면 PH 번호가 일치하면 0010부터 0070까지의 전체 레코드를 원하시나요 $PH_NO"? 그러면 이 sedoneliner가 작동합니다.

sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
  • /^0010/,/^0070/H예약된 공간에 0010에서 0070 사이의 레코드를 추가합니다.
  • /^0010/h0010은 추가하면 안 되지만 새 레코드를 시작하므로 예약된 공간에 복사됩니다.
  • /^0070/! d0070 항목이 아니면 더 이상 처리나 출력이 발생하지 않습니다.
  • x;/|$PH_NO| PH Number/! d"이제 전체 레코드가 패턴 공간에 있도록 공백을 바꾸고 해당 번호가 포함되어 있지 않으면 제거하십시오.

답변2

for r in `grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed 's/,[0-9]\+,/,/g'`; do sed -n "$r"p CUSTOMER_FILE; echo; done

149 196 222위 명령에는 고객의 전화번호가 있습니다. 찾으시는 전화번호로 변경해주세요.

CUSTOMER_FILE당신이 찾고 있는 파일입니다. 파일 이름으로 변경하세요.

코드를 bash 스크립트에 넣고 149 196 222로 바꾸고 로 $1바꿀 수도 있습니다 . find-customer.sh라고 말하면 다음과 같은 스크립트를 실행할 수 있습니다.CUSTOMER_FILE$2

./find-customer.sh '149 196 222' your-file-name

이 코드의 전제 조건:

  1. Bash, GNU 환경(GNU grep, GNU sed)
  2. 파일은 아래 형식을 따라야 합니다. 0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file>


고쳐 쓰다

이것은 고성능 버전입니다. (적어도 위의 원본보다 높습니다. for 루프가 전혀 포함되지 않습니다.)

grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed -r 's|([0-9]+),[0-9]+,([0-9]+)|\1,\2p;\2a|g' | sed -n -f - CUSTOMER_FILE


AIX용 업데이트

질문자는 AIX에서 작업 중이기 때문입니다. AIX의 grep은 컨텍스트 옵션 -A, -B, -C를 지원하지 않습니다.

인터넷에는 이 문제를 해결하는 다양한 "cgrep"(컨텍스트 grep) 구현이 있습니다(GNU grep 컨텍스트 옵션을 에뮬레이션). 그러나 대부분은 GNU grep과 동일한 출력을 제공할 수 없습니다. 내가 찾은 GNU grep 컨텍스트 옵션 중 가장 가까운 옵션은 단 하나뿐입니다. 링크는https://stackoverflow.com/questions/1685678/advanced-grep-unix/1685782#1685782

이 경우에 필요한 몇 가지 수정을 했습니다.

#!/bin/bash
BEFORE=$1
AFTER=$1
FILE=/tmp/.cattmp
PATTERN="$2"
cat > $FILE
for i in $(grep -n "$PATTERN" $FILE | sed -e 's/\:.*//')
  do head -n $(($AFTER+$i)) $FILE | tail -n $(($AFTER+$BEFORE+1))
done
rm $FILE

이 파일을 다른 이름으로 저장 하고 위 명령의 내용을 바꾸 grep-context.sh세요 .grep -C1./grep-context.sh 1

제가 생각하는 또 다른 방법은 AIX에서 GNU grep을 컴파일하는 것입니다. (만일을 대비해 GNU sed도 컴파일하세요)

답변3

다음 스크립트를 사용할 수 있습니다.

#!/bin/sh
read START
read END
read MATCH

REND=$(grep -n "$END" lines | tail -1 | cut -d":" -f 1)
RSTART=$(grep -n "$START" lines | head -1 | cut -d":" -f 1)

sed $RSTART,$REND!d lines | grep "$MATCH"

파일에 넣고 이 명령을 사용하여 실행 권한을 추가하세요.

chmod +x script.sh

시작 변수:출발선 번호(예: 0010)

종료 변수:최종 변수(예: 0070)

일치하는 변수:한 줄에서 찾고 있는 단어/문자/숫자(예: 0012)

RSTART 변수:텍스트 파일의 시작 줄 번호(예: 1)

찢어짐 변수:텍스트 파일의 시작 줄 번호(예: 32)


편집하다:

마지막 줄을 다음과 같이 변경하여 줄이 몇 번 반복되는지 확인할 수도 있습니다.

sed $RSTART,$REND!d lines | grep "$MATCH" | sort | uniq -c

관련 정보