パターンの前に/textlineを挿入する - 直前ではない

パターンの前に/textlineを挿入する - 直前ではない

請求書ファイルを前処理し、各請求書を別々のファイルに分割しようとします。請求書は複数のページで構成できます。各ページのタイトルは次のとおりです。







                                                                 121084
                                                                   A134
                                                               09.17.19
                                                                      1

各ページの上部には6つの空白行があり、その後に請求書番号、顧客番号、日付、ページ番号(そして請求書の残りの部分)が表示されます。

各ページの10行目(各ページの10行目は、請求書ページ番号)の「1」(70個のスペースの後に「1」が続く)ごとに、1行目にいくつかのテキストを挿入する必要があります(区切り文字として使用)。分割ファイル)。請求書は複数のページで構成できますが、「1」(70個のスペースの後に「1」が続く)は新しい請求書であることを意味します。

「1」が表示されたら(70個のスペースの後に「1」が続く)、その上の9行(この請求書の最初の行)空白行にテキストを挿入したいと思います。ファイル内のすべての項目に対してこれを行います。その後、各請求書のファイルを別々のファイルに分割できます。

sedを使用してパターンの直前にデータを挿入できることを知っていますが、その上に9行のデータを挿入するにはどうすればよいですか?

私は通常sedとawkでそれをすることができますが、これは私をパニックにさせます。

ベストアンサー1

あなたが言いたいことが次のとおりであるとしましょう。

複数の請求書を含む長いファイルがあります。すべての請求書はテキストで始まります70 spaces and a 1。各請求書の内容の前に新しい内容の9行を挿入する必要があります。

それでは10行を集めるだけです。現在の行が次のような場合請求書の開始最初の行に新しいテキストを挿入します。

実際、これは次のように達成できます。

sed -e '1{N;N;N;N;N;N;N;N}' -e 'N;l;/\n \{70\}1$/{iNew content here' -e 'P};P;D' file

または長い形式(一部のsed実装にはコメントは適用されません):

sed '1{                              # (only) on the first line
         N;N;N;N;N;N;N;N             # accumulate 9 lines (first one plus 8 more).
      }
     N                               # On every line,also accumulate that line 
     /\n \{70\}1$/{                  # If buffer ends ($) in 70 spaces and a "1"
i\
New content added here               # insert the content of this line at
                                     # the start of the buffer (10 lines above).
                       P             # and then print it.
                  }
     P;D                             # close the N cycle above by
                                     # printing and deleting one line
    ' file                           # On the selected file.

解決策は、awk請求書の開始を示す行にRSを設定することです。この場合、FSを改行に設定すると各行がフィールドに分割され、$(NF-9)は上記の9行目を参照します。

awk -v ln=9 '
              ( NF < ln ){ print; next };           # not enought fields?
                                                    # include
                         { $(NF-ln) = "New Text to include" newln $(NF-ln);
                           print                    # and print
                         };
              BEGIN{ breakln = sprintf("%71s",1);   # 70 spaces and a 1
                     newln   = sprintf("\n");       # a newline
                     RS      = breakln newln;       # set the Record Separator
                     FS      = "\n";                # set the Field separator
                     OFS     = FS;                  # print what got removed
                     ORS     = RS                   # print what got removed
                   }
            ' file

または(シェル/awkソリューション):

breakln="$(printf '%71s' 1)";
newl=$'\n';
awk '  (NF<ln){print;next};
              { $(NF-ln)="New Text to include\n"$(NF-ln); print}' \
    ln=10 \
    RS="$breakln$newl" \
    FS="$newl" \
    OFS="$newl" \
    ORS="$breakln$mewl" \
    file

おすすめ記事