awkを使用したリストの並べ替え

awkを使用したリストの並べ替え
#!/bin/bash

PASTE=$(xclip -o)

curl -s https://website.com/$PASTE | dos2unix | grep -A3 '<td class="hidden-xs"' | sed 's/<[^>]*//1g; s/>//g; s/  //g; s/\\r//g; /^$/d; s/--/-/g; s/&#246;/ö/g; s/&#252;/ü/g; s/&#231;/ç/g' | awk '!/^Genel/ || !f++'

次の結果が生成されます。

General
hit
definition 1
-
General
hit
definition 2
-
... 
-
Idiom
hit the sack
Definition 
-
Idiom
hit the buffers
Definition 1
-
Idiom
hit the buffers
Definition 2

私はそれを分類しようとし、次の結果を得ました。

General
hit
definition 1
definition 2
definition ...
-
Idiom
hit the sack
Definition 
-
hit the buffers
Definition 1
Definition 2

答え1

使用awk:

awk '
$0=="General" || $0=="Idiom"{
  type=$0;  getline
  group=$0; getline

  key=type","group  
  if (key in b){
    b[key]=b[key]"\n"$0
  }
  else {
    if (type=="General" && !isfirstgeneral){
      type=type"\n"; isfirstgeneral=1
    }
    else if (type=="Idiom" && !isfirstidiom){
      type=type"\n"; isfirstidiom=1
    }
    else {
      type=""
    }
    a[++cnt]=key
    b[key]=type group"\n"$0
  }
}
END{
  for (i=1;i<=cnt;i++){
    print b[a[i]]
    if (i<cnt) print "-"
  }
}' file

行がまたGeneralはの場合、Idiomこの行をとして保存し、次のtype2行(group「定義済み」と呼ばれる$0)を取得します。

awkループ中に配列要素が乱れないようにするには、2つの配列をトリックとして使用します。

  • 整数キーを持つ配列には、次の行で構成されるa配列のキーが格納されます。btypegroup
  • 配列はb特定のキーに対して収集された文字列を保持します。

配列のキーの組み合わせが存在しない場合は、b2つの新しい配列要素を作成します。文字列はtype最初に見つかったときにのみ保存されます(出力にバグがある場合は-blockを削除してにif-else if-else置き換えます)。b[key]=type group"\n"$0b[key]=type"\n"group"\n"$0

キーが存在する場合は、「定義」文字列が既存の配列値に追加されます。

このセクションでは、END配列順序を使用して配列値を印刷し、区切り線を使用します。ba

(入力をファイルとして保存しましたが、必要に応じてfileコマンド出力をこのawkスクリプトにパイプすることができます。)curl

出力:

General
hit
definition 1
definition 2
-
Idiom
hit the sack
Definition
-
hit the buffers
Definition 1
Definition 2

修正する

カテゴリリストを使用するには、カテゴリごとに1行ずつテキストファイルにカテゴリを追加します。

categories.txt:

General
Idiom
Computer
What ever

スクリプトを次に変更します。

awk '
NR==FNR{
  cat[$0]; next
}
$0 in cat{
  type=$0;  getline
  group=$0; getline

  key=type","group  
  if (key in b){
    b[key]=b[key]"\n"$0
  }
  else {
    a[++cnt]=key
    b[key]=group"\n"$0
  }
}
END{
  for (i=1;i<=cnt;i++){
    # print first occurrence of category
    catname=a[i]
    sub(/,.*/, "", catname)
    if (catname in cat){
      print catname
      delete cat[catname]
    }

    print b[a[i]]
    if (i<cnt) print "-"
  }
}' categories.txt file

答え2

awk連想配列の使用は少し恥ずかしいです...

awk '$0=="General"||$0=="Idiom"{
    cat=$0;getline; def=$0; getline;
    (cat=="General")?gen[def]=gen[def]"\n"$0:idi[def]=idi[def]"\n"$0
}END{
    print "General";for (g in gen) print g, gen[g]"\n-";
    print "Idioms";for (i in idi) print i, idi[i]"\n-"
}' file

出力:

General
hit 
definition 1
definition 2
-
Idioms
hit the buffers 
Definition 1
Definition 2
-
hit the sack 
Definition
-

もちろん、これはすべての定義が「一行」であると仮定します。

カテゴリをもっと見るカテゴリが表示される順序について心配しないでください...

awk '{
    cat=$0; getline; phr=$0;getline; def=$0; getline;
    cats[cat];defs[phr]=cat;txt[phr]=txt[phr]"\n"def
}END{
    for (c in cats) {
        print c":"; for (d in defs) {
            if (defs[d]==c) print d, txt[d]"\n-"
        }
    }
}' file

入力する

General
hit
Strike a blow.
-
General
hit
A successful search result. 
-
Idiom
hit the sack
Go to bed.
-
Idiom
hit the buffers
Reach the end of the line.
-
Idiom
hit the buffers
Reach the limit.
-
Bananas
Banana
A Banana

出力

Bananas:
Banana 
A Banana
-
Idiom:
hit the buffers 
Reach the end of the line.
Reach the limit.
-
hit the sack 
Go to bed.
-
General:
hit 
Strike a blow.
A successful search result. 
-

カテゴリ出力を見つけたのと同じ順序で制御するには、カテゴリを列挙するか、すべての|sに対してcat(例えば)で区切られた文字列を生成し、splitそれを列挙配列に入れてから、他の配列のイテレータ。

これは実際にはアイテムの4行の順序によって異なります。

関連情報