次のファイルがあります:
cat fileA.txt
seattle 1991 west
atlanta 1993 west
turlock 1998 west
marysville 2004 south
newyork 2007 north
canada 2004 west
2 番目のファイルは次のようになります。
cat fileB.txt
popular
someWhatPopular
boring
popular
popular
popular
次のような出力を取得したいと思いますfileB.txt
:
popular popular popular someWhatPopular boring popular
つまり、私は3列fileB.txt
目に並べ替えようとしているのですfileA.txt
次のコードを試しました:
#!/bin/bash
sort -s -k3,3 fileA.txt fileB.txt
しかし、うまくいきませんでした。何か提案はありますか? ハードコーディングを必要としないものなら何でも結構です。Bash/awk/sed など。
答え1
これは Linux の問題というよりも、データ構造の問題です。リンクするには、両方のテーブルに共通のエントリ (キー) が必要です。これは、他の「データベース」の場合と同じです。また、データ テーブルの最初の列に一意のキーを保持しておくことをお勧めします。そうすれば、好きなだけ並べ替えやリンクを行うことができます。
@glennjackman マッピングのようなものを例にとると、マッピングキーを北、南などとして定義します。
1 south somewhatPopular
2 west popular
3 north boring
4 east unexplored
ファイル というファイルpopularity
。fileA
一意のキーを含めるように修正する
1 seattle 1991 west
2 atlanta 1993 west
3 turlock 1998 west
4 marysville 2004 south
5 newyork 2007 north
6 canada 2004 west
次に、選択したキーでこれらのファイルを操作できますjoin
(この場合、の列2はのpopularity
列4にマップされますfileA
)。ただし、join
両方のファイルをキーフィールドでソートする必要があります。
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity) | sort -k2 | awk '{print $6}'
popular
popular
popular
somewhatPopular
boring
popular
少し強引なアプローチですが、最大限の柔軟性が得られます。
上記のコマンドを各パイプで分割すると、各ステップで何が行われるかがわかります。
編集:説明join -1 4 -2 2 # its in the man pages
これは、join
表 1 の 4 列目 (-1 4) を見て、表 2 の 2 列目 (-2 2) で一致する値を見つけるように指示します。
join
次に、2つのテーブルの列を1つのテーブルにまとめますが、キー列(北など)は1つだけ含めます。
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity)
そしてそれはより明確になるはずだ
動作させるためにデータテーブルを並べ替える必要があったためjoin
、
| sort -k2
結合されたテーブルを元の順序に戻します。
必要な列は結合された表の6列目なので、
| awk '{print $6}'
stdout に出力します。
答え2
paste
2 つの「テーブル」ファイルを一緒にして、出力を にパイプしsort
、cut
4 番目の列のみを保持してみることもできます。
未テストの(現時点では携帯電話での)試みは次のようになります
paste fileA fileB | sort -s -k3,3 | cut -f4
答え3
アルファベット順のマッピングは以下で取得できます。
paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)
north boring
south popular
west someWhatPopular
そして、awk を使用して、希望する出力形式を生成できます。
awk '
NR==FNR {map[$1] = $2; next}
{print map[$NF]}
' <(paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)) fileA.txt
someWhatPopular
someWhatPopular
someWhatPopular
popular
boring
someWhatPopular