텍스트 처리 - 패턴 B 일치 선이 처음 나타날 때까지 패턴 A 일치 선을 얻는 방법은 무엇입니까?

텍스트 처리 - 패턴 B 일치 선이 처음 나타날 때까지 패턴 A 일치 선을 얻는 방법은 무엇입니까?

패턴과 일치하는 행을 역순으로 가져오고 싶습니다.패턴의 첫 번째 발생과 일치하는 라인두번째선과 선이 통과하는 선을 일치시킵니다.

고쳐 쓰다:example_file.txt

ISA*00*          *00*          *ZZ*SIX-SIX6      *12*666666666666     *66666666*6666*U*666666666*6666666666*0*P*\
GS*FA*SIX-SIX-SIX*666666666*6666666*6666*6666*X*66666
ST*666*666
AK1*SX*666
AK2*777*6666666
AK5*A
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5
AK2*777*6666666
AK5*A
AK2*777*69696969
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5
AK9*P*20*20*19
SE*69*6969
GE*1*6767
IEA*1*0000000000

내가 원하는 것은 AK5다음과 같이 아래에서 위로 모든 패턴을 얻는 것입니다.R

무늬:AK5*R

패턴이 처음 나타날 때까지 모든 행을 위로 올리십시오.두번째일치합니다. 예를 들어:

무늬두번째:AK2

원하는 출력:

첫 번째 모드일치하는 사람이 호출됩니다E1

AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5

고쳐 쓰다:두 번째 모드일치하는 사람이 호출됩니다E2

AK2*777*69696969
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5

패턴이 2개 이상인 경우 등성냥.

편집하다:완료할 수 있다는 것을 알고 있지만 sed, 패턴 B의 첫 번째 발생과 일치하는 각 패턴 A에서 행을 가져와 추가 처리를 위해 임시 텍스트 파일에 저장하는 것은 여전히 ​​운이 없습니다.

sed사용 가능한 모든 패턴을 가져오는 예제 명령은 다음과 같습니다.두번째내부에example_file.txt

sed -ne '/AK2\*/,/\AK5\*R/p' example_file.txt

명령 논리 시나리오 예:

A="AK5\*R"
B="AK2"

find the first $A < example_file.txt; # AK5\*R
move to previous line until first occurrence of $B line; # AK2*any_number*any_number
get all lines from first $A to its first occurrence of $B and store in a text file; # result > e1.txt
# The same way goes to the second occurrence of pattern A.

(참고: $B가 처음 발생한다는 것은 모든 $A 행에서 시작하여 $A 행과 일치하는 첫 번째 행이 나올 때까지 이전 행을 가져오는 것을 의미합니다. 예를 들어 첫 번째 $A 행이 중간에서 시작하는 경우 라인 50과 같은 파일의 라인이고 파일에 총 100개의 라인이 있으면 명령이 처음으로 보는 $B 라인을 만날 때까지 거기에서 이전 라인으로 이동합니다(아래 예 참조).

예제_파일2.txt

ISA*00*          *00*          *ZZ*SIX-SIX6      *12*666666666666     *66666666*6666*U*666666666*6666666666*0*P*\
GS*FA*SIX-SIX-SIX*666666666*6666666*6666*6666*X*66666
ST*666*666
AK1*SX*666
AK2*777*6666666
AK5*A
AK2*777*7777777
AK5*A
AK2*777*888888
AK5*A
AK2*777*7777777
AK5*A
AK2*777*5555555
AK5*A
AK2*777*7777777
AK5*A
AK2*777*4545435
AK5*A
AK2*777*7777777
AK5*A
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*A
AK2*777*0987654
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*A
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*A

산출:

AK2*777*0987654
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5

답변1

귀하의 설명을 다시 읽으면서 패턴 B의 첫 번째 일치부터 패턴 A의 첫 번째 일치(위쪽)까지 아래에서 위로 이동하고 싶다는 것을 이해합니다. 단, 생성되는 부분은 파일 순서대로 이루어져야 합니다.

여기에는 많은 논리가 필요합니다. 다음과 같은껍데기스크립트가 모든 작업을 수행합니다. 결과를 올바른 내부 순서로 파일과 일부 숫자에 넣으십시오 E. 첫 번째 파일 ( E1)은 위에서부터 첫 번째 일치 항목을 가지며 마지막 파일은 마지막 일치 부분을 갖습니다.

#!/bin/bash

rm -rf resE* E*

tac ../example_file.txt |
    awk 'BEGIN{i=1}
         /^AK5\*R.*/{p=1}
         {if(p==1){f="resE" i;print($0)>>f;close(f)}}
         /^AK2.*/{if(p==1){i++};p=0}
        '
set -- resE* 
c=$#
for (( i=1;i<=$c;i++)); do
    pos=$(($c-$i+1))
    [ -f "$1" ] && tac "$1" > "E$pos"
    shift
done

결과 범위는 다음과 같습니다.

$ cat E1
AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5

$ cat E2
AK2*777*7777777
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5

답변2

POSIXex다시 구출하러 오세요!

exPOSIX 지정 스크립트 가능 파일 편집기입니다. 일반적으로 역방향 주소 지정과 관련된 문제에 대해서는 Awk 또는 Sed보다 더 나은 솔루션입니다.

다음 문장이 당신에게 딱 맞습니다 example_file2.txt:

printf '%s\n' 'g/AK5[*]R/?AK2?,.p' | ex example_file.txt

귀하의 컴퓨터에서도 example_file.txt작동하지만 g전역 명령은 ex각 범위에 대해 별도의 대상을 작성할 수 없으므로 필요한 두 출력 파일은 다음과 같이 병합됩니다.

AK2*777*7777777
AK3*S6*5**3
AK3*A2*5**3
AK4*3*6969*4
AK4*7*6969*4
AK5*R*5
AK2*777*69696969
AK3*J7*5**3
AK4*3*6969*4
AK5*R*5

그러나 이는 처리하기 쉽습니다. csplit"컨텍스트"를 기반으로 파일을 분할하도록 설계된 다른 POSIX 도구를 사용하십시오.

휴대용 POSIX 솔루션:

patA='AK5[*]R'
patB='AK2'

printf '%s\n' "g/$patA/?$patB?,.p" |
  ex example_file.txt |
  csplit -f my_unique_prefix_ -n 1 -s -k - "/$patB/" '{999}'

for f in my_unique_prefix_*; do
  mv "$f" "e${f##my_unique_prefix_}.txt";
done

rm e0.txt

이를 완벽한 솔루션으로 만드는 마지막 요소는 파일 번호를 역순으로 다시 지정하는 것입니다. 이 부분은 아직 해보지 못했습니다.


파일 번호가 파일과 같은 순서인지 상관 없고, 확장자를 생략해도 상관 없고 , 파일 번호가 from 대신 from 으로 되어도 .txt상관 없다면 , 각 파일 메시지에 몇 줄이 추가되었는지에 대한 진단을 인쇄해도 괜찮습니다. 그러면 다음과 같이 단순화할 수 있습니다.e01e1

patA='AK5[*]R'
patB='AK2'

printf '%s\n' "g/$patA/?$patB?,.p" |
  ex example_file.txt |
  csplit -f e -k - "/$patB/" '{999}'

rm e00

관련 정보