使用awk中的行和列信息生成新行

时间:2015-02-20 06:12:30

标签: awk

我有一个文件,输入的格式如下所示。 “word”“frq”和“word_meanings”将对应于第1,2和3列。在第1列中有单词,在第2列中有数字,在第3列中有单词的含义。我想将第3列中的含义相互配对,以便在输出中它们在同一行中,如果它们对第1列具有相同的“单词”。我还想使用“frq”列中的数字来决定这些意义如何相互配对。

输入:

word frq  word_meanings

door  12  meaning_a
door  25  meaning_b
door  3   meaning_c
hand  20  meaning_d
hand  17  meaning_e
floor 4   meaning_f
floor 30  meaning_g
floor 20  meaning_h
floor 4   meaning_e

输出类似于

door meaning_b meaning_a
door meaning_b meaning_c
hand meaning_d meaning_e
floor meaning_g meaning_h
floor meaning_g meaning_e
floor meaning_g meaning_f

对于解释,因为'meaning_b'的frq值为25,所以对于以单词door开头的所有列,它具有最高的frq值,因此'meaning_b'用于创建具有其他含义的对。其他行有门作为第一列的单词。

2 个答案:

答案 0 :(得分:1)

通过对文件进行两次传递,您可以使用第一个来收集具有最高频率的含义,使用第二个来打印具有这些含义的每一行。

在awk中执行该操作的标准方法是使用NRFNR。当NR == FNR(当前总记录数等于当前文件中的记录号)时,您知道您是第一次处理该文件。通过使用next语句结束该块,您可以跳过后面的操作并直接读取文件的下一行。

如果您到达第二个操作块,您知道您正在第二次读取该文件,您可以在其中打印每行的结果。

不要忘记在awk命令行上传递两次文件!每次通过一次。

这种技术适用于各种“连接”应用程序(在这种情况下,是自连接)。

$ cat words.txt
door  12  meaning_a
door  25  meaning_b
door  3   meaning_c
hand  20  meaning_d
hand  17  meaning_e
floor 4   meaning_f
floor 30  meaning_g
floor 20  meaning_h
floor 4   meaning_e


$ cat words.awk
NR == FNR {
    # first pass, build array of meanings with max freq
    if (max_frq[$1] < $2) {
      max_frq[$1] = $2;
      max_meaning[$1] = $3;
    }
    next;
}

{
    # second pass, print words and meanings with those collected in first pass
    if (max_meaning[$1] != $3) {
       print $1, max_meaning[$1], $3;
    }
}


$ awk -f words.awk words.txt words.txt
door meaning_b meaning_a
door meaning_b meaning_c
hand meaning_d meaning_e
floor meaning_g meaning_f
floor meaning_g meaning_h
floor meaning_g meaning_e

编辑

要更改输出分隔符,可以在命令行上设置OFS

$ awk -v OFS=, -f words.awk words.txt words.txt
door,meaning_b,meaning_a
door,meaning_b,meaning_c
hand,meaning_d,meaning_e
floor,meaning_g,meaning_f
floor,meaning_g,meaning_h
floor,meaning_g,meaning_e

答案 1 :(得分:1)

按字和frq排序,然后让awk处理细节:

sort -k1,1 -k2,2nr | 
awk '$1 != word {word = $1; means = $3} means != $3 {print word, means, $3}'

输出:

door   meaning_b  meaning_a
door   meaning_b  meaning_c
floor  meaning_g  meaning_h
floor  meaning_g  meaning_e
floor  meaning_g  meaning_f
hand   meaning_d  meaning_e