2017-01-28 7 views
0

ファイル内の行の位置を変更する方法(できればsedを使用する方法)を知りたいと思います。例えば、私は私が FORALL線の位置を変更し、ゴール後にそれを持って、このsedを使ってファイル内の行の位置を変更する

goal identifier statement 
forall statement 
let statement 1 
let statement 2 
other statements 

を行うことができるようにしたいと思い

goal identifier statement 
let statement 1 
let statement 2 
forall statement 
other statements 

を含むファイルを検討しライン。 forallおよびゴールは、行の識別に使用できる正規表現です。

+0

これは興味深い問題であるためにはawkを使用する必要があります。それのStackOverflowの良い質問にするために、追加してくださいコードを使用してソリューションを実現しようとしました。[MCVE](http://stackoverflow.com/help/mcve)と[how-to-ask](http://stackoverflow.com/help/)を参照してください。どのような良い質問があるかについてのいくつかのガイドラインについては、いくつかのガイドラインのページを参照してください。 – ghoti

答えて

4

あなたが最初のケースでは、取得する場所A>B

sed -n '2{h; :a; n; 4{p;x;bb}; H; ba}; :b; p' file 

またはA<B

sed -n '2{h; d}; 4{p; x;}; p' file 

line 2への移行line 4のために、私はline Bline Aを移動したい、試すことができます:へline 4を移動しますline 2

goal identifier statement 
forall statement 
let statement 1 
let statement 2 
other statements 

あなたは後者の場合には、取得:line 2

goal identifier statement 
let statement 2 
forall statement 
let statement 1 
other statements 

説明

sed -n '    #silent option ON 
    2{    #if is line 2 
     h    #Replace the contents of the hold space with the contents of the pattern space 
     :a   #label "a" 
     n    #fetch the next line 
     4{   #if is line 4 
      p   #print line 4 
      x   #Exchange the contents of the hold and pattern spaces 
      bb  #goto "b" 
     } 
     H    #appends line from the pattern space to the hold space, with a newline before it. 
     ba   #goto "a" 
    } 
    :b    #Label "b" 
    p     #print 
' file 

EDIT

あなたはregexを使用するための行を特定したい場合は、次のことができ

line 4に移動し最初のコマンドを変更する

sed -n '/goal/{p;n;h;:a;n;/forall/{p;x;bb};H;ba};:b;p' file 
+1

正規表現のマッチに基づいて行を移動したいと思うでしょうか? – 123

+0

@ 123それは本当です、私は誤解しています、私は変更するつもりです –

+1

@ 123私はmi postを編集しました、ありがとうございました –

1
$ cat r.awk 
BEGIN { 
    forall_re = "^forall" # examples of regexps 
    goal_re = "^goal" 
} 

function tag(l) { # tag a line 
    if  (l ~ goal_re ) return "goal" 
    else if (l ~ forall_re) return "forall" 
    else     return "rest" 
} 

{ # store entire file in array; give a tag to every line 
    lines[NR] = $0 
    tags[NR] = tag($0) 
} 

function swap0(a, i, j, tmp) { 
    tmp = a[i]; a[i] = a[j]; a[j] = tmp 
} 

function swap(i, j) { 
    swap0(lines, i, j); swap0(tags, i, j) 
} 

function rise(i) { 
    # TODO: add error check 
    while (i - 1 > 0 && tags[i - 1] != "goal") { 
     swap(i, i - 1); i-- 
    } 
} 

function process( i) { 
    for (i = 1; i <= NR; i++) 
     if (tags[i] == "forall") rise(i) 
} 

function dump( i) { # print the array 
    for (i = 1; i <= NR; i++) 
     print lines[i] 
} 

END { 
    process() 
    dump() 
} 

$ cat r.txt 
goal identifier statement 
let statement 1 
let statement 2 
forall statement A 
other statements 

goal identifier statement 
let statement 1 
let statement 2 
forall statement B 
other statements 

使用上の入力ファイルの例:sedの

$ awk -f r.awk r.txt 
goal identifier statement 
forall statement A 
let statement 1 
let statement 2 
other statements 

goal identifier statement 
forall statement B 
let statement 1 
let statement 2 
other statements 
1

は、個々のライン上の単純な置換のためであり、それはすべてです。何か他のもののためにあなたがソフトウェアのすべての望ましい属性(明瞭さ、シンプルさ、移植性、等:

$ awk 'NR==FNR{if (/forall/) {f=FNR; v=$0} next} FNR!=f; /goal/{print v} ' file file 
goal identifier statement 
forall statement 
let statement 1 
let statement 2 
other statements 
0
sed -r '/goal/{     # if match "goal" line 
    :X       # this is a lable for branch command 
    N       # append next line 
    /forall[^\n]*$/{   # if match "forall" line move to "goal" line below 
     s#^([^\n]*)(.*)(\n[^\n]*)$#\1\3\2# 
     b      # after move finished branch to end 
    } 
    bX       # branch to :X for appending next line 
}' file 
goal identifier statement 
forall statement 
let statement 1 
let statement 2 
other statements 
+0

上記の問題を解決する*方法*の簡単な説明を追加してください。 – Leigh

関連する問題