好吧,正在寻找一种快速的方法来做到这一点。我有一个文本数据文件中需要更改的行号列表。该行上的 16 位模式可以是任何内容,但我需要将其更改为XXXXXXXXXXXXXXXX
仅根据行号进行读取。我再次有一长串我知道需要更改的行号。需要更改的线条没有明显的模式。 (我没有写数据模式,但我知道需要更改哪些行才能读取所有 X。)我阅读了这里的很多答案,但没有一个真正解决这个问题。
如果这还不清楚,我会用另一种方式来表达......
将文件中的第 26115、32198、37256、40001、40023 行更改为读取XXXXXXXXXXXXXXX
.在 190 万行文件中,我有超过 100,000 行需要更改。
答案1
作为@Gilles答案的扩展,因为你说你有文件中需要更改的行号(我假设已排序并调用linums
)
awk '
BEGIN { getline NEXT < "linums" }
NR == NEXT { $0 = "XXXXXXXXXXXXXXX"; getline NEXT < "linums" }
1
'
这可以很好地扩展以更改数千行,而无需手动键入这数千行号。
或者,通过稍加修改,您可以获取要更改的行号或文件stdin
。我会为此制作一个脚本(我称之为redact.awk
)
#!/usr/bin/awk -f
BEGIN {
LINUMS = ARGV[1]
ARGV[1] = ARGV[2]
--ARGC
getline NEXT < LINUMS
}
NR == NEXT {
$0 = "XXXXXXXXXXXXXXX"
getline NEXT < LINUMS
}
1
然后您可以使用以下任何一个:
$ ./redact.awk linums file-to-be-changed
$ ./redact.awk - file-to-be-changed
$ ./redact.awk linums -
$ ./redact.awk linums
(后两者是等价的)
答案2
sed 或 awk 都可以很好地完成此任务。
sed '
26115 s/.*/XXXXXXXXXXXXXXX/
32198 s/.*/XXXXXXXXXXXXXXX/
37256 s/.*/XXXXXXXXXXXXXXX/
40001 s/.*/XXXXXXXXXXXXXXX/
40023 s/.*/XXXXXXXXXXXXXXX/
'
awk '
NR==26115 || NR==32198 || NR==37256 || NR==40001 || NR==40023 {$0 = "XXXXXXXXXXXXXXX"}
1
'
1
(在前面的代码执行可能的转换之后,单独的打印所有行。)
答案3
sed -e '1{x;s/^/XXXXXXXXXXXXXXX/;x;}
26115bp
32198bp
37256bp
40001bp
40023bp
d
:p
g
' data_file
我们首先用所需的模式填充保留空间XXXXXXXXX
,然后通过跳转到标签 :p 来仅调用所需的行号,该标签将检索保留空间,然后将其隐式转移到标准输出。不匹配的行将被删除(如果要保留它们,请将 更改d
为)。b
答案4
由于替换是静态的,并且替换多行的操作在 中非常简单sed
,因此可以创建一个sed
大脚本来完成这项工作。
假设您将行号放在一个单独的文件中,linenos.txt
每行一个行号,那么我们可以sed
通过以下方式生成(GNU)脚本:
$ awk '{ printf("%dc XXXXXXXXXXXXXXX\n", $0) }' linenos.txt >script.sed
或者
$ awk '{ print $0, "c XXXXXXXXXXXXXXX" }' linenos.txt >script.sed
然后,将其应用到文件中:
$ sed -f script.sed file >file.new
注意:我从未运行过非常大的sed
脚本,所以我不知道 GNU 如何在sed
性能方面处理它。