テキスト処理 - パターン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

修正する:2番目のモード一致する人が呼び出されます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行に一致する最初の行が出るまで前の行を取得することを意味します。開始する場合は、行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各範囲に対して別々のターゲットを作成できないため、必要な2つの出力ファイルは次のようにマージされます。

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

関連情報