$START부터 $END까지 그리고 $MIDDLE에 일치 항목이 포함된 행 세트에 대한 Grep

$START부터 $END까지 그리고 $MIDDLE에 일치 항목이 포함된 행 세트에 대한 Grep

"0010|"의 라인 세트에 대한 Grep/Awk/Sed "0070|"으로 $PH_NO에 일치하는 항목이 포함된 AND

아래는 샘플 데이터입니다. 0012 필드에 있는 전화번호와 0010부터 0070까지의 해당 전체 고객 레코드를 검색해야 합니다. 하나의 데이터 파일에는 동일한 전화번호를 가진 두세 개의 고객 레코드가 포함될 수 있으며 이를 모두 가져와야 합니다.

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/H0010부터 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-loop가 전혀 포함되지 않습니다.)

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)

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


편집하다:

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

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

관련 정보