web-dev-qa-db-ja.com

任意の列の共通値を使用して行をマージします

以下に示すようなタブ区切りのファイルがあり、いずれかの列の一致に基づいて行をマージしたいと思います。列の数は通常2ですが、場合によっては3になることもあります。

入力:

Amazon NILE 
ALASKA NILE
HELLO MY
MANGROVE Amazon
MY NAME
IS NAME

必要な出力:

Amazon NILE ALASKA MANGROVE
HELLO MY NAME IS

awkでこれをどのように行うことができますか?

これは以下のファイルでも機能しますか?入力:

Apple_bin2file       strawberry_24files
mango2files      strawberry_39files
Apple_bin8file       strawberry_39files
dastool_bin6files  strawberry_40files
Apple_bin6file       strawberry_40files
orange_bin004file      dastool_bin004files
orange_bin005file      dastool_bin005files
Apple_bin3file       dastool_bin3files
Apple_bin5file       dastool_bin5files
Apple_bin6file       dastool_bin6files
Apple_bin7file       dastool_bin7files
Apple_bin8file       mango2files

タブ区切り形式で期待される出力:

Apple_bin2file strawberry_24files
mango2files strawberry_39files Apple_bin8file
dastool_bin6files strawberry_40files Apple_bin6file
orange_bin004file dastool_bin004files
orange_bin005file dastool_bin005files
Apple_bin3file dastool_bin3files
Apple_bin5file dastool_bin5files
Apple_bin7file dastool_bin7files

答えてくれてすみません、入力ファイルを更新しました!

1
Susheel Busi

GNU awkを使用する

gawk '
    {
        grp = 0
        # see if any of these words already have a group
        for (i=1; i<=NF; i++) {
            if (group[$i]) {
                grp = group[$i]
                break
            }
        }
        # no words have been seen before: new group
        if (!grp) {
            grp = ++n
        }
        # if we have not seen this Word, add it to the output
        for (i=1; i<=NF; i++) {
            if (!group[$i]) {
                line[grp] = line[grp] $i OFS
            }
            group[$i] = grp
        }
    }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"
        for (n in line) {
            print line[n]
        }
    }
' input.file

最初の入力で:

Amazon NILE ALASKA MANGROVE
HELLO MY NAME IS

2番目の入力(出力をcolumn -tにパイプする)の場合:

Apple_bin2file     strawberry_24files
mango2files        strawberry_39files   Apple_bin8file
dastool_bin6files  strawberry_40files   Apple_bin6file
orange_bin004file  dastool_bin004files
orange_bin005file  dastool_bin005files
Apple_bin3file     dastool_bin3files
Apple_bin5file     dastool_bin5files
Apple_bin7file     dastool_bin7files
0
glenn jackman

正確にあなたの与えられた例のために、試してみてください

awk '
    {for (j=1; j<=MX; j++)  {for (i=1; i<=NF && !(m=match (LN[j], $i)); i++);
                 if (m) {$i = ""
                     break
                    }
                }
     LN[j] = LN[j] $0 " "
     if (j>MX) MX = j
    }
END {for (l in LN) print LN[l]
    }
' file3
Amazon NILE  ALASKA  MANGROVE  
HELLO MY  NAME IS  

編集:新しいデータで、これは機能するはずです:

awk '
        {for (j=1; j<=MX; j++)  {m = 0
                                 for (i=1; i<=NF; i++)  {if (match (LN[j], $i)) {$i = ""
                                                                                 m = 1
                                                                                }
                                                        }
                                 if (m) break
                                }
         LN[j] = LN[j] $0 OFS
         if (j>MX) MX = j
        }
END     {for (l in LN)  {gsub (/ +/, OFS, LN[l])
                         gsub (OFS"+", OFS, LN[l])
                         print LN[l]
                        }
        }
' OFS="\t" file
0
RudiC