文字列で始まるフィールドに従ってファイルをソートする

文字列で始まるフィールドに従ってファイルをソートする

次のように構造化されたファイルがあるとします

/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf

ファイルを次のように並べ替えたいと思います:

/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf

つまり、アルファベット順で、文字列に従ってAuthor-...

ご覧のとおり、 の位置はAuthor-...一定ではありません。

これどうやってするの?

答え1

次のbashコマンドを試してください:

sort -t- -d -k2 -o output.txt input.txt

4 つのオプションと入力ファイルの名前がありますinput.txt。このファイルが現在のディレクトリにない場合は、 を指定する必要がありますpath/to/the/folder/input.txt。オプションとその引数は次のとおりです。

  • -t はフィールド区切り記号を示します。-区切り記号として使用し、その前後のすべてが-別々の列とみなされるようにします。
  • -d は辞書ソートを示します。たとえば、Apple は Berry の前にあります。
  • -k2 は、並べ替えの基準となる列 (この場合は 2 番目の列) を示します。最初の列は、最初の より前のすべての列であることに注意してください-。たとえば、です/home/zz/BOOKS/Author。2 番目の列は、最初の と 2 番目の の間にあります。-つまり、 です。Artemis
  • -o はoutput.txtソートされた出力を端末ではなくファイルにリダイレクトします。

お役に立てれば

答え2

この例ではやりすぎですが、user68186の回答で提案された解決策GNU awk では、より一般的には次のようなことができます。

gawk -F/ '
  function mycmp(i1,v1,i2,v2) {
    m = split(v1,a);
    n = split(v2,b);
    return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
  }
  {
    lines[NR] = $0
  }
  END {
    PROCINFO["sorted_in"] = "mycmp";
    for(i in lines) print lines[i]
  }
' file

最後の後のすべての単語の語彙値に従って並べ替えられることに注意してください/。つまり、フォーマットAuthor-<author name>-<title>.<extension>

  • 固定文字列Author-(すべての行で同じ重みを持つため、効果はありません)
  • <author name>-; それから
  • <title>.; それから
  • <extension>

sortこれは、GNUの単純な KEYDEFの動作に似ています。-t- -k2つまり、有効なソート キーは から始まり<author name>、行末まで続きます。

呼び出しでは明示的な区切り文字が省略されるsplitため、 の値が継承されFS、異なるパス区切り文字を使用するシステムでは簡単に変更できます。関数に追加された空文字列は、""ファイルmycmp名が数値であっても字句比較を強制します。例を参照してください。awk が文字列と数値を変換する方法


コマンドを使い続ける場合はsort、GNU awkの別のプロセスとの双方向通信に:

  • /文字列の先頭の最後の - 区切りフィールドを複製します。
  • 結果をsortコマンドに渡す
  • ソートされた結果を読み取り、重複したプレフィックスを削除して印刷します。

つまり

gawk -F/ '
  BEGIN {OFS=FS; cmd = "sort -d"} 
  {print $NF $0 |& cmd} 
  END {
    close(cmd,"to"); 
    while(cmd |& getline){$1 = ""; print};
    close(cmd,"from")
  }
' file

/ここでは、絶対パス ( で始まる行) が最初の空のフィールドを意味するという点で、少しずるい点があります。相対パスを処理するには、print $NF $0を に変更してprint $NF,$0「欠落している」区切り文字を挿入し、その後、sub()より単純な の代わりに正規表現を使用して$1 = ""先頭の要素を削除する必要があります。

これにより、純粋なソリューションよりも高速かつメモリ効率が向上する可能性があるだけでなくgawk、他のsortオプションも簡単に追加できるようになりますcmd = "sort -d -t " FS " -k1,1r"。例:

関連情報