4

私はUNIXコーディングにかなり慣れていないので、1行ずつ逆方向に読み取る必要のあるファイルがあります。このファイルには、{}内にコードのセクションがあります。次に、この反転ファイルを入力としてawkスクリプトを実行する必要があります。サポートスタッフにtacをインストールしてもらいますが、その前に、必要なものが出力されるかどうか、または誰かが代替案を提案できるかどうかを知りたいと思います。

このファイルには、次の形式のデータが含まれています。

page 0 0 0 none
{
   layer 0 0 0 "1line" 0 8 8 3
   {
      sector 0 -1 0 32 
      {
        point_name 0 0 34543 34 44 1 1 0
        status 1 0 1 0 1 431232 "transformer" 23 12
        analog 1 0 1 0 1 321234 11.5 43 1 1 0
        ...
        ...
        ...
        device 1 0 1 "ground" 32 56 1 1 0
      }
    }
}

{}を保持したいのですが、{}の間の行を逆にして、出力が次のようになるようにします。

page 0 0 0 none
{
   layer 0 0 0 "1line" 0 8 8 3
   {
      sector 0 -1 0 32 
      {
        device 1 0 1 "ground" 32 56 1 1 0
        ...
        ...
        ...
        analog 1 0 1 0 1 321234 11.5 43 1 1 0
        status 1 0 1 0 1 431232 "transformer" 23 12
        point_name 0 0 34543 34 44 1 1 0
      }
    }
}

また、tacは入力ファイルを上書きしますか、それとも別のファイルとして保存しますか?

4

2 に答える 2

1

ほとんどのUNIX (スタイル)ツールと同様tacに、元のファイルを上書きしたり、新しいファイルを書き込んだりすることはありません。stdout新しいファイルを書き込むには、tacリダイレクトを使用します。tac file > newfileこれにより、反転fileしたファイルがに保存されnewfileます。必要なことを一人で行うことはできませんtac。スクリプトが必要です。

これが1つですawk

{
    # store each line in the array line
    line[n++] = $0
} 

/{/ {
    # get the line number of the last line containing {
    first=NR
}

!/}/ {
    # get the line number of the last line not containing }
    last=NR
} 

END {
    # print first section in order
    for (i=0;i<first;i++) 
        print line[i]
    # print second section in reverse order
    for (i=last-1;i>=first;i--)    
        print line[i]
    # print last section in order
    for (i=last;i<NR;i++) 
        print line[i]
}

これをファイルに保存してからreverse実行しますawk -f reverse file

$ awk -f reverse file
page 0 0 0 none
{
   layer 0 0 0 "1line" 0 8 8 3
   {
      sector 0 -1 0 32 
      {
        device 1 0 1 "ground" 32 56 1 1 0
        ...
        ...
        ...
        analog 1 0 1 0 1 321234 11.5 43 1 1 0
        status 1 0 1 0 1 431232 "transformer" 23 12
        point_name 0 0 34543 34 44 1 1 0
      }
    }
}

リダイレクトを使用して、新しいファイルを作成しますawk -f reverse file > newfile

于 2013-01-10T13:41:11.437 に答える
1

tacファイルの行順を逆にするだけなので、目的を達成するにはもっと強力なものが必要になります。また、すべてのシェル ツールには、「一時」ファイルを使用せずに入力ファイルを上書きする手段が含まれているわけではありません。一部のツール ( sedPerlなど) には、「インプレース編集」オプションと呼ばれるものがあり、バックアップ ファイルのサフィックスが指定されていない場合、ファイルの上書きという最終結果が得られます。

目的を達成するには、 を使用することをお勧めしawkます。次のように実行します。

awk -f script.awk file > newfile

一時ファイルを使用して入力ファイルを上書きするには、次を実行します。

awk -f script.awk file > temp && mv temp file

の内容script.awk:

/{/ {
    print (a ? a ORS : "") $0
    f=1; a=b=""
    next
}

f && !/}/ {
    a = (a ? a ORS : "") $0
    b = $0 (b ? ORS b : "")
    next
}

/}/ && b {
    print b ORS $0
    a=b=f=""
    next
}1

結果:

page 0 0 0 none
{
   layer 0 0 0 "1line" 0 8 8 3
   {
      sector 0 -1 0 32 
      {
        device 1 0 1 "ground" 32 56 1 1 0
        ...
        ...
        ...
        analog 1 0 1 0 1 321234 11.5 43 1 1 0
        status 1 0 1 0 1 431232 "transformer" 23 12
        point_name 0 0 34543 34 44 1 1 0
      }
    }
}

別の方法として、次の 1 つのライナーがあります。

awk '/{/ { print (a ? a ORS : "") $0; f=1; a=b=""; next } f && !/}/ { a = (a ? a ORS : "") $0; b = $0 (b ? ORS b : ""); next } /}/ && b { print b ORS $0; a=b=f=""; next }1' file

説明:

最初のコード ブロックは、行に左中かっこが含まれているかどうかを尋ねます。その場合、レコード 'a' に続いて現在のレコード (左中かっこを含む行) を出力します。フラグを設定し、レコード「a」と「b」を削除して、残りのコードの処理をスキップします。

2 番目のブロックは、フラグが設定されていて、行に右中括弧が含まれていない場合にのみ実行されます。ここで、2 つのレコード 'a' と 'b' を作成します。行に左中括弧が含まれている場合、レコード 'a' が出力されることを思い出してください。したがって、「最初から最後まで」の向きで構築する必要があります。次に、'end to start' 方向でレコード 'b' を作成します。'next' は、残りのコードの処理をスキップします。

3 番目のブロックは、行に右中括弧とレコード 'b' が含まれている場合に実行されます (これは、逆向きで作成されたレコードであることを思い出してください)。次に、レコード 'b' に続いて現在の行 (右中かっこのある行) を出力します。レコード 'a'、'b' を削除し、フラグをリセットします。'next' は、残りのコードの処理をスキップします。末尾の「1」は、デフォルトの印刷を有効にします。

于 2013-01-10T14:40:24.387 に答える