使用 sed 对文本文件中的数字进行批量转换

使用 sed 对文本文件中的数字进行批量转换

目前,我有多个包含数百万行的文件,如下所示:

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

相关内容