目前,我有多个包含数百万行的文件,如下所示:
565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15
数字 565 和 564 是 ID,我从各个文件中提取了所有唯一 ID,并将它们连接成一个文件,如下所示:
565
564
182
982
接下来我想对原始文件中的数字进行以下转换:
565 -> 1
564 -> 2
182 -> 3
982 -> 4
原始文件将如下所示:
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
我知道如何使用 sed 应用单一转换,但是有没有方法可以在文本文件中指定转换方式,并使用 shell 脚本将其应用于原始文件?
谢谢。
答案1
如果要以单调方式增加第一个字段,则不需要使用额外的文件进行映射或第一个字段,只需将awk
第一个字段设置为行(记录)号:
awk '{$1=NR} 1' file.txt
它将以空格作为新的字段分隔符重建整个记录,但在这种情况下我认为我们是安全的,因为字段是由空格分隔的。
现在,这里有解决您问题的方法,如果您有一个额外的文件,比如说id.txt
第一个字段:
最好使用可以理解行号并跟踪它们的工具,例如awk
:
awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt
假设,
id.txt
仅包含提取的第一列,并且file.txt
是主文件NR==FNR {a[$0]=NR; next}
将文件的每个记录保存id.txt
为关联数组的键a
,其值为相应的行号。next
确保不会对记录进行进一步处理id.txt
{$1=a[$1]}
将第一个字段设置为相应数组元素的值;请注意,这需要以空格作为分隔符来重建整个记录,但我想在这种情况下,我们可以安全地利用这种简洁性。1
只是一个用于解释的占位符true
,以便之后打印整个记录
如果您觉得有趣,您可以使用一些标准的 *nix 工具,借助进程替换(<()
)bash
最后paste
:
paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt)
nl id.txt | cut -f1
获取行号cut -d' ' -f2- file.txt
获取除第一个之外的所有字段
例子:
% cat file.txt
565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15
182 10 12 23 18 17 25
892 1 7 12 13 16 18 40 29 15
% awk '{$1=NR} 1' file.txt
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
3 10 12 23 18 17 25
4 1 7 12 13 16 18 40 29 15
% cat id.txt
565
564
182
892
% awk 'NR==FNR {a[$0]=NR; next} {$1=a[$1]} 1' id.txt file.txt
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
3 10 12 23 18 17 25
4 1 7 12 13 16 18 40 29 15
% paste -d' ' <(nl id.txt | cut -f1) <(cut -d' ' -f2- file.txt)
1 0 10 12 23 18 17 25
2 1 7 12 13 16 18 40 29 15
3 10 12 23 18 17 25
4 1 7 12 13 16 18 40 29 15
答案2
awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed ids.txt
它将读取你的“ids”文件并创建一个id列表,以便进行搜索和替换sed
。
$ cat pattern.sed
s/^564/1/
s/^565/2/
...
如果你的 ID 不是唯一的,你可以使用:
sort ids.txt | uniq | awk 'BEGIN {OFS=""} {print "s/^", $0, "/", ++count, "/"}' > pattern.sed
为了使其更有效率,然后运行:
$ sed -i.bk -f pattern.sed file
$ cat file
2 0 10 12 23 18 17 25
1 1 7 12 13 16 18 40 29 15
1 1 7 12 13 16 18 40 29 11111
1 1 7 12 13 16 18 40 29 15555
2 0 10 12 23 18 17 2555
...
如果您希望对最终文件进行排序,请使用sort -k1,1 file > file.sorted
。