【问题标题】:Merging lines of a text file and sorting based on the order of elements in another text file合并文本文件的行并根据另一个文本文件中元素的顺序进行排序
【发布时间】:2014-08-22 17:16:56
【问题描述】:

我有两个未排序的文本文件,如下所示,它们的行数不一定相同:

在 A.txt 中,我们每行只有一个唯一元素:

a7
a1
a5
a2
a6
a8
a4

在 B.txt 中,每一行都有一个唯一的元素对:

a1 a2
a7 a6
a1 a5
a5 a8
a1 a4
a2 a1
a4 a5
a6 a7
a8 a2

如果有多个具有共同第一个元素的对,我首先想以某种方式合并 B.txt 的行,第二个元素必须像这样连接:

TempAB.txt

a1 a2 a5 a4
a7 a6
a5 a8
a2 a1
a4 a5
a6 a7
a8 a2

然后最终输出的顺序必须和A.txt一样,比如:

AB.txt

a7 a6
a1 a2 a5 a4
a5 a8
a2 a1
a6 a7
a8 a2
a4 a5

使用 awk 有什么建议吗?

【问题讨论】:

  • 您是否真的需要该中间文件,或者您只是认为这是生成最终文件的必要方法?您希望 B.txt 中以 A.txt 中不存在的值开头的行做什么,例如a3 或者这永远不会发生?
  • unix.com/shell-programming-and-scripting/… 找到第一部分的代码 .... awk 的 != $1 || NR ==1{s=$1;if(p){打印 p};p=$0;next} {sub($1,"",$0);p=p""$0;}END{打印 p}' B .txt
  • @Ed Morton:不,没有必要。我只是想一步一步地解释。
  • 不要假设你在任何网站或论坛上找到的 awk 代码,包括这个,是合理的,除非你从新闻组 comp.lang.awk 获得它,它会被所有的awk 专家。你发布的那个sn-p是不合理的。

标签: awk text-processing


【解决方案1】:

您可以使用以下awk 单行:

创建临时数据:

awk '{a[$1] = (a[$1]?a[$1] FS $2:$2)}END{for(x in a) print x,a[x]}' b.txt
a1 a2 a5 a4
a2 a1
a4 a5
a5 a8
a6 a7
a7 a6
a8 a2

您可以将输出重定向到另一个文件,例如 b.tmp

要实现第二个输出,你可以这样做:

awk 'NR==FNR{a[$1]=$0;next}{print (($1 in a) ? a[$1] : $1)}' b.tmp a.txt 
a7 a6
a1 a2 a5 a4
a5 a8
a2 a1
a6 a7
a8 a2
a4 a5

如果你真的不需要中间文件,那么你可以绕过它,然后做:

awk 'NR==FNR{a[$1]=(a[$1]?a[$1]FS$2:$0);next}{print(($1 in a)?a[$1]:$1)}' b.txt a.txt 
a7 a6
a1 a2 a5 a4
a5 a8
a2 a1
a6 a7
a8 a2
a4 a5

【讨论】:

  • 请注意,如果 $1 的值曾经计算为数字零,它将无法填充 a[]
【解决方案2】:
$ awk 'NR==FNR {a[$1]=($1 in a?a[$1] FS:"")$2; next} {print $1, a[$1]}' B.txt A.txt
a7 a6
a1 a2 a5 a4
a5 a8
a2 a1
a6 a7
a8 a2
a4 a5

【讨论】:

  • 和处理special case的+1。
  • 谢谢,我也给你扔了一个。我们俩都没有处理的一种特殊情况是,来自 B.txt 的 $1 从未出现在 A.txt 中,但 OP 没有告诉我们是否/如何处理。
  • 是的,我想删除数组条目并处理 END 块中的条目,但不想让它过于复杂。 :)
  • 对,我也是这么做的。
猜你喜欢
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
相关资源
最近更新 更多