AWK

2017-09-26 3 views
1
私はテキストの列の可変数を並べ替えしようとしています

を使用して、最後の列を使用してアルファベット順に並べ替え、時には3つのフィールドは、時には2AWK

例の入力がありますがあります:

  George W. Bush 
     John F. Kennedy 
     Micky Mouse 
     Brack Obama 

私はそう$3または$2フィールドを使用して、姓のアルファベット順にそれらを取得したいです。

これまでのところ、私は各行を反転させて最後に名字を付けました。しかし、それらを並べ替えるために私はそれらを元に戻すように見えることはできません。 Iveは配列を試したところ、負荷が多くなり、期待された(繰り返し)。

私はこれをawkファイルとしてのみ保持したいと考えています。

別のawkファイルを使ってawkファイルのスクリプトを作り直すことを考えましたが、awkの中で(bashスクリプトを使って)ファイルを作成できません。私はを読んできました。の実用ガイドですが、私が見た例は全く同じようです。私の質問を見直してくれてありがとう。

は現在、これは、私はそれは私がそれを望むように並べ替えられます及ん値を私に残し

{ 
     #print $3 " " $1 " " $2; 
     if($3 == ""){ 
      #print "me"; 
      print $2 " " $1; 
      #list[$3]= $2" "$1 
     }else{ 
      print $3" "$1" "$2 ; 
      #list[$3]= $3" " $2" "$1;} 
      #for(result in list){ print list[result]; } 
     } 
    } 


    gawk -f fileUsed alphRecoredToBeUsed | sort 

を行って取得しています方法です。ただし、アルファベット順を維持しながら、最初の元の値を提示します。

+0

期待される出力をコードタグに投稿してください。 – RavinderSingh13

答えて

4

$ awk '{print $NF "\t" $0}' file | sort | cut -f2- 
George W. Bush 
John F. Kennedy 
Micky Mouse 
Brack Obama 
+0

入力の順序によっては、「Robert F. Kennedy」と「John F. Kennedy」が間違った順序で表示される可能性があります。 –

+0

OPは姓でソートされた出力を必要とします。これはおそらく、複数の人が同じ姓を持ち、awkスクリプトが何をしているのかというと、入力順を保持することを意味します。姓が重複していれば、他の注文がより良い、またはより正確であると考える理由はありません。 sort'は、姓が重複しているファーストネームでソートされます。これも正しいかもしれませんが、そうでなければ、OPは '-k1,1'を追加することができます。私の主なポイントは、自然に「正しい」注文がなく、「間違った」注文がないということです。 OPは重複をどうするかについて何も言わなかったので、順序は正しい。 –

0

私の好きなawk変数の1つは、レコード内のフィールド数であるNFです。つまり、数字は$1$2 ... $NFここで、$NFは最後の要素です。 を入力してawkの2番目のを最後の要素に印刷したり、必要があれば$(integer-after-math)という表記法で他の計算をしたりすることもできます。

すべてをスワップするのではなく、データの各行の最後の名前である$NFに基づいて整理してください。ここで

2

は、各行の最後の言葉に基づいてソートするgawkは使用するスクリプトです:

#!/bin/sh 
gawk ' 
function compare(i1, v1, i2, v2) { 
    ct1 = split(v1, pcs1) 
    ct2 = split(v2, pcs2) 
    f1 = ct1 < 1 ? "" : pcs1[ct1] 
    f2 = ct2 < 1 ? "" : pcs2[ct2] 
    if (f1 < f2) return -1; 
    if (f1 > f2) return 1; 
    return 0 
} 
{ lines[++ct] = $0 } 
END { 
    asort(lines, sorted_lines, "compare"); 
    for (i = 1; i <= length(sorted_lines); i++) 
     print sorted_lines[i] 
} 
' "[email protected]" 

それはあなたの例のために働く:

$ cat input 
George W. Bush 
Brack Obama 
Micky Mouse 
John F. Kennedy 
$ ./s input 
George W. Bush 
John F. Kennedy 
Micky Mouse 
Brack Obama 

(私はgawkの4.0.1を使用しています)、

0

ここでは、1行のawkコマンドを使用して、目的の出力を得るコマンド

$ awk '{a[$NF]=$0} END{PROCINFO["sorted_in"]="@ind_str_asc"; for(i in a)print a[i]}' file 
     George W. Bush 
     John F. Kennedy 
     Micky Mouse 
     Brack Obama 

簡単な説明、

  • 使用$NF$0マップを作成するための配列a[$NF]=$0
  • PROCINFO["sorted_in"]="@ind_str_asc":文字列として比較される昇順でインデックス順に並べ替えられます。詳細については、awk manualを参照してください。それが特定のものであることを心配してくださいgawk
  • for(i in a)print a[i]:以前に定義されたアレイスキャンオーダーのため、配列はascendinの順番でスキャンされます。
+0

ブッシュsr。彼の息子George H.W.が入力ファイルに現れ、そのうちの1人だけが選出され、訂正され、印刷されます。 –

+0

はい、そうです。この方法では、最後のフィールドの順序だけをスキャンできます。 – CWLiu

-1

すべてフィールドはこれを価値あるものにするために必要です。

ワンライナー:

$ awk '{s="";for (i=1;i<NF;i++)s=s $i;a[s]=$0}END{n=asorti(a,b);for(j=1;j<=n;j++)print a[b[j]]}' input.txt 

説明:

{ 
    s=""         # initialize s 
    for (i=1;i<NF;i++) s=s $i   # concatenate first and middle names 
    a[$NF s]=$0       # use last name followed by other names 
             # as index 
} 
END{ 
    n=asorti(a,b);      # sort index of a 
    for(j=1;j<=n;j++) print a[b[j]]  # print results 
} 

この入力使用:

$ cat input.txt 
George W. Bush 
George H.W. Bush 
Michelle Obama 
Barack Obama 
Micky Mouse 
John F. Kennedy 

を与える:

$ awk '{s="";for (i=1;i<NF;i++)s=s $i;a[$NF s]=$0}END{n=asorti(a,b);for(j=1;j<=n;j++)print a[b[j]]}' input.txt 
George H.W. Bush 
George W. Bush 
John F. Kennedy 
Micky Mouse 
Barack Obama 
Michelle Obama 

そしてGNUからのご参加の機能を使用することができます4.1をawkは:GNU AWKで

@include "join" 
{ 
    n=split($0, a, " ") 
    s=join(a, 1, n-1) 
    b[$NF s]=$0 
} 
END{ 
    n=asorti(b,c); 
    for(j=1;j<=n;j++) print b[c[j]] 
} 
+1

'H.W.'が' Hのようなスペースで区切られている場合。 W.'(私はそうなるだろうと思う)この解決策は私に最初の 'ジョージW.ブッシュ'とその後 'ジョージH・ブッシュ'を与える。それが私の解決策で試して解決した問題の1つでした。 –

+1

Wikipediaは違った考え方をしています:https://nl.wikipedia.org/wiki/George_H.W._Bush –

+0

もう一度:https://en.wikipedia.org/wiki/George_R._R._Martin。また、英国のwikipedia:https://en.wikipedia.org/wiki/George_H._W._Bush –

-1

$ awk ' 
{ 
    b=$NF     # initialize the key buffer 
    if(NF>1)    # if there are more than one word in the name 
     for(i=1;i<NF;i++) # add them to the buffer 
      b=b OFS $i 
    a[b]=$0    # hash 
} 
END{ 
    PROCINFO["sorted_in"]="@ind_str_asc" # order on the index using for 
    for(i in a) 
     print a[i] 
}' file 

出力(テストのためのリストにいくつかの通常の容疑者を追加):

George H. W. Bush 
George W. Bush 
John F. Kennedy 
John G. Kennedy 
Madonna 
Micky Mouse 
Barack Obama 
Brack Obama 

スクリプトをハッシュするキーとしてlastname firstname_if_exists 1st_middle_if_existsなどを使用します。 a["Bush George H. W."]="George H. W. Bush"。 sorted_in用のGNU AWKで

+0

ここでは、以前のソリューションと比較して新しいものはありません。 Pls。あなた自身を説明してください。 –

+0

'for'を使用しているだけではありません。 @ CWLiuの答えに言及されている問題を解決し、明らかに新しい問題を導入しています。)最後の名前だけでなく、名前の中のすべての単語を逆順に使って注文します。 @ CWLiuの答えからコピーされた –

+0

.. –

2

これは、より簡単であるかもしれない:

$ awk ' 
    { a[$NF]=($NF in a ? a[$NF] ORS : "") $0 } 
    END { PROCINFO["sorted_in"]="@ind_str_asc"; for (i in a) print a[i] } 
' file 
George W. Bush 
John F. Kennedy 
Micky Mouse 
Brack Obama 

、または任意のawkとは、ソート+カット+

sh-4.4$ awk '{print $NF,$0}' file |sort -k1|awk '{$1="";print $0}'                             
George W. Bush                                          
John F. Kennedy                                          
Micky Mouse                                           
Barack Obama 

行われているもの:最後の名前を前面に表示し、並べ替えてから出力から削除します。

これが役に立ちます

+0

うわー、そのような種類の重いサブシェルが生まれました(ユーティリティとパイプごとに1つ)。また、 'cat file ...'を実行していて実際にファイルを連結していない場合は、おそらく 'cat' *の不要な使用(UUOcと呼ばれます)です。最低でも 'awk '{print $ NF、$ 0}'ファイル名の答えを短くすることができます。 ... 'とUUOc ':を除く)') –

+0

ちょっと@ DavidC.Rankinありがとう、私は答えを編集しました。 :)これは、要求している人が望んでいることを願っています –

+0

これは、努力のためのAです。 UUOcの削除作業がうまくいっていて、ソート順は問題ありません。 –