패턴과 일치하는 행을 역순으로 가져오고 싶습니다.ㅏ패턴의 첫 번째 발생과 일치하는 라인두번째선과 선이 통과하는 선을 일치시킵니다.
고쳐 쓰다: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
다시 구출하러 오세요!
ex
POSIX 지정 스크립트 가능 파일 편집기입니다. 일반적으로 역방향 주소 지정과 관련된 문제에 대해서는 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
상관 없다면 , 각 파일 메시지에 몇 줄이 추가되었는지에 대한 진단을 인쇄해도 괜찮습니다. 그러면 다음과 같이 단순화할 수 있습니다.e01
e1
patA='AK5[*]R'
patB='AK2'
printf '%s\n' "g/$patA/?$patB?,.p" |
ex example_file.txt |
csplit -f e -k - "/$patB/" '{999}'
rm e00