同じファイルからブロックごとに値を取得する

同じファイルからブロックごとに値を取得する

次の内容を含む「SAMPLE.txt」というファイルがあります。

P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2

出力ファイル「RESULT.txt」が欲しい。

Value1:123456
Value2:98765
Value3:NULL

まず、P1とP2部分の間のコンテンツをインポートしてから、10,9 * /値を見つけて別の値として保存する必要があります。特定のP1-P2ブロックにこの値がない場合は、「NULL」として保存したいと思います。

上記のコードをshell / awkにどのように書きますか?

私はスクリプトに初めて触れました。

答え1

これは機能し、完全に移植可能です。

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' 

プロセスは次のとおりです。

  1. まず^扱います。P1

  2. 現在の行が!一致しない場合はd削除されます。

  3. その場合は、次のようP1に交換してください。Value:

  4. :n次に、extタグを設定してNext行を取得します。

  5. 見つから\nP2ない場合は、extタグに戻り、見つかるまでもう一度やり直してください。!b:n

  6. :.*\n10,9次に、最初の発生/まですべての文字の発生を削除します。

  7. \n最初に使用可能なewlineと後続のすべての文字を削除します。

  8. :最後の文字が後に続くコロンの場合、文字Value列が挿入されますNULL

手順6と7が機能します。手順6では、\n目的の数値文字列の前にあるewlineを削除しますが、そうでない場合は、次の\newlineは次の文字列になりますValue:すべてステップ7に進みます。

これが実際に動作するものです:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' <<\DATA
P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2
DATA

出力:

Value:123456
Value:98765
Value:NULL

答え2

使用perl(ファイル全体をメモリに保存しても):

 perl -0777 -ne 'while (/P1\n(.*?)\nP2/gs) {
   printf "Value%d:%s\n", ++$n, $1 =~ /^10,9.*\// ? $'\'': "NULL"}'

答え3

一方perl通行:

$ perl -F'/' -alne '
    if (/P1/../P2/ and $_ !~ /^P/) {
        print "Value@{[++$i]}:",$F[1]?$F[1]:"NULL";
    }
' file
Value1:123456
Value2:98765
Value3:Null

解決策awk

$ awk -F'/' '/P2/{f=0};/P1/{f=1;next};f{print "Value"++i":"($2?$2:"Null")}' file
Value1:123456
Value2:98765
Value3:Null

答え4

みんなありがとうございます。ついに私の問題を解決したコードスニペットは次のとおりです。

nawk -v fname="${filename}" -F '/|:' '

    function isnum(x){return(x==x+0)}

    /P1/,/P3/{
            # Found start increment i reset variables go to next line
            if(/P1/){
                   ++i 
                   fid ="" 
                   count++
                   next
                }

            # Found end validate variable and print go to next line
            if(/P3/){
                printf "%s|",count
                printf "%s|",isnum(fid)?fid:"NULL"
                  next 
                }
            if(!fid && /36,59:*/)
                {
                    fid = $NF
                }
        ' ${filename} >>output.txt

しかし、もう別の問題が発生し、それに対して別のスレッドを作成しました。

あなたが助けることができる場合は、こちらのリンクをご覧ください。

https://stackoverflow.com/questions/24277167/finding-and-replacing-text-inside-awk-block?noredirect=1#comment37509363_24277167

関連情報