2017-11-06 14 views
1

オリジナルファイルは次のようになります。変更列の順序(列の数が異なる)

stat.sn 15094 291 usf=630 ind=32615 on_2=ON-14-6003 spd=307 i_pow=150 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 on_2=ON-14-6003 spd=307 i_pow=150 
stat.sn 15094 276 usf=630 ind=32615 on_2=ON-14-6003 spd=307 i_pow=150 

そして、私はそれがこのようなことする必要があります。

stat.sn 15094 291 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 276 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 

は単に言った:on_2が行に存在する場合行の最後の値にする必要があります。 残りの値の順序は変わらないはずです。存在する場合は

は、常に第六フィールドon_2ある - IND後とSPD前に。すべてのフィールドは、各行で同じ位置にあります。

私はawkがこれを行うことができると思いますが、それを行う方法を理解できません。

+1

何か試しましたか? awkがこれを実現できるという知識があったと仮定します。 – Inian

+0

@EdMortonは、存在する場合には最後の値/列になるようにon_2を入れ、他のものと同じ順序を保持します。 – Branko

+0

あなたの質問には、 "on_2"フィールドが常に同じ場所に現れるかどうか(そしてあなたの例を更新しない場合)など、これまでに述べられていない要件を述べる質問があります。 –

答えて

1
$ awk '$6 ~ /^on_2=/{$(NF+1)=$6; $6=""; $0=$0; $1=$1}1' file 
stat.sn 15094 291 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 276 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 

WRT:

$6=""が、それは空白の前と後の葉、つまり、foo<blank>$6<blank>barfoo<blank><blank>barへの変更$ 6が今nullでありますフィールドの数は変更されず、$ 5はまだfooであり、$ 7は依然としてbar

$0=$0を使用するとawkは$0をフィールドに再分割します。したがって、fooとbarの間の複数の空白は1つのfiedセパレータとして扱われるため、$ 6はまだfooですが、$ 6はbarです。この線。これは$ 0を変更しなかったので、$ 0はまだfooとbarの間に2つの空白を含んでいますが、個々のフィールドの割り当てにどのように分割されたかが変更されました。それでは$1=$1を使用して(または任意のフィールドに割り当てる)

はfooの間の唯一の1つのブランクがあります。この後のように、フィールド間OFS値(空白文字)を使用して$ 6再コンパイル、バーするためにawkの原因となる代わりに、2

したがって、$ 0 = $ 0は$ 1 - > $ NFと$ 1 = $ 1の新しい値を作成し、それらの間のすべてのFSをOFSに置き換えます。

+0

なぜあなたは '$ 0 = $ 0; $ 1 = $ 1'は整列を修正しました。ありがとうございます。 – thanasisp

+0

私の解答を説明で更新しましたが、 –

1

これが(GNU sed)に役立つかどうか教えてください。

sed -r 's/(on_2=[^ ]+)(.*)/\2\1/' Input_file 

出力は以下のようになります。

stat.sn 15094 291 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 276 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 

出力をタブ区切りにする場合。

sed -r 's/(on_2=[^ ]+)(.*)/\2\1/' Input_file | column -t 
+0

sedは 'on_2'より前の接頭辞と一致する必要はありません。それは少しコードを縮小します。 – HuStmpHrrr

+1

良い考えですが、 '[^(on_2)]'はあなたの考え方をしません: 'on 'not_2'"とマッチしません - '' '' n'または '_'または' 2'または ')'を使用します。 'sed -r 's /(on_2 = [^] +)(。*)/ \ 2 \ 1 /' file'を入力してください。 –

+0

@glennjackman、ありがとうございました。 – RavinderSingh13

2

したがって、一致するたびに末尾の列$ 6を移動します。場合

awk '$6 ~ /^on_2/ { t=$6; $6=$7; $7=$8; $8=t } 1' file 

パターンマッチングは、任意の列に存在する可能性があり、我々は最後に、常にそれを印刷したいです。

awk '{ 
    for(i=1;i<NF-1;i++) 
     if($i~/^on_2/) { 
      t=$i; 
      for(j=i;j<NF;j++) 
       $j=$(j+1); 
      $NF=t 
     } 
    } 1' file 

我々はt=$i; $i=""を設定し$0 tを印刷することにより、このシフトを省略することができたが、その後余分FSアライメントを破壊、移動列の位置に印刷されています。


更新:$(NF+1)=i; $i=""を使用してアライメントを維持する、このanswerの確認方法について。

+1

はOPの望ましい出力を提供しません。 –

+0

@glenn jackmanありがとうございました、実際にはOPが求めているスワップではありませんでした。私はシフトを行う答えを更新したので、今はあまり効率的ではないようです。 – thanasisp

2

単純に:on_2が1つの行に存在する場合は、 行の最後の値にする必要があります。残りの値の順序は変わらないはずです。

所望の出力を得るためにいくつかのより多くの方法、on_2が存在する場所は重要で、検索、抽出、無効と最後の列としてそれをしない:

$ awk 'match($0,/on_2=[^ ]* /){s=substr($0,RSTART,RLENGTH);sub(s,"");$0=$0 FS s}1' infile 
stat.sn 15094 291 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 276 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 

説明:

awk 'match($0,/on_2=[^ ]* /){    # Search 

     s=substr($0,RSTART,RLENGTH);  # if found extract it 

     sub(s,"");       # remove extracted part from row 

     $0=$0 FS s       # set extracted part at the end 

    }1          # print line/record 
    ' infile 
  • match($0,/on_2=[^ ]* /) - record/liのregexp(on2=[^ ]*)を検索するゼロ無制限の時間との間のマッチ - NE /行

    /on_2=[^ ]* /

    • on_2=on_2=文字通り(大文字と小文字を区別)
    • 一致[^ ]*
    • *数量詞以下のリストに存在しない単一文字の文字にマッチしますできるだけ多くの時間、必要に応じて返す(欲張り)
    • 文字が文字通りnsitive)
  • ​​一致した場合には、レコードから文字列を抽出し、それを保存する変数s

  • sub(s,"") - nullを持つレコード/行中のSの文字列、代替の検索

  • $0=$0 FS s - レコード/行/行の変更

  • }1- 1最後にデフォルト操作つまり、現在の/レコード/行の印刷、print $0です。 awkの動作を知るには、awk '1' infileが全てのレコード/行を出力しますが、awk '0' infileは何も表示しません。ゼロ以外の数値は,となり、デフォルトの動作がトリガされます。

1

$0=$0; $1=$1、フォーマットのために必要である理由別sed

$ sed -r 's/(\son_2=\S+)(.*)/\2\1/' file 

stat.sn 15094 291 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 361 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 360 usf=630 ind=32658 spd=307 i_pow=150 
stat.sn 15094 272 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
stat.sn 15094 276 usf=630 ind=32615 spd=307 i_pow=150 on_2=ON-14-6003 
+0

はい、そうです。一定。 – karakfa

+0

'-r'はgnuのみで、代わりに' -E'を使用します.gnuとosx sedsで動作します。 –

関連する問題