使用sed从文本文件中删除特定的行号?


Answers:


374

如果要删除第5至10和12行:

sed -e '5,10d;12d' file

这会将结果打印到屏幕上。如果要将结果保存到同一文件中:

sed -i.bak -e '5,10d;12d' file

这会将文件备份到file.bak,并删除给定的行。

注意:行号从1开始。文件的第一行是1,而不是0。


32
并非所有的Unix都带有“ -i”。不要犯回退到“ sed cmd文件>文件”的错误,这会清除您的文件。
PRA

4
如果我想删除第五行直到最后一行怎么办?
尔根·保罗

14
@WearetheWorldsed -e '5,$d' file
Brian Campbell

1
@BrianCampbell我应该怎么做才能只删除特定行?
Kanagavelu Sugumar 2014年

14
@KanagaveluSugumar sed -e '5d' file。语法是<address><command>;其中<address>可以是一行,也可以是5范围内的行5,10,该命令将d删除给定的一行。这些地址也可以是正则表达式,也可以是$表示文件最后一行的美元符号。
布莱恩·坎贝尔

50

您可以删除特定的单行及其行号,方法是

sed -i '33d' file

这将删除33行号上的行并保存更新的文件。


1
在我的情况下,“ sed”删除了错误的行。所以我用这个方法:sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'。谢谢!
爱德华多·卢西奥

同样在这里,我写了一个循环,奇怪的是有些文件丢失了正确的行,但是有些文件也丢失了另一行,不知道出了什么问题。(GNU / Linux bash4.2)下面的awk命令在循环中效果很好
FatihSarigol

如果要从行列表中删除,请非常小心使用sort -r,否则您的第一个sed将更改其他所有行的行号!...
Konchog

要评论在循环中删除错误的行:请确保以最大的行号开头,否则每条被删除的行将抵消行号……
Skippy le Grand Gourou

25

还有awk

awk 'NR!~/^(5|10|25)$/' file

2
注意:awk系列对我而言比sed变体(在OS-X和Ubuntu Linux之间)更可靠地工作
Jay Taylor

3
请注意,这不会删除文件中的任何内容。它只是打印文件,而没有这些行到标准输出。因此,您还需要将输出重定向到临时文件,然后移动该临时文件以替换原始文件。
mivk 2015年


6

这通常是反模式的症状。产生行号的工具很可能会被替换为立即删除行的工具。例如;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

deletelines您想像中的实用程序在哪里)与

grep -v error logfile

话虽如此,如果您确实需要执行此任务,则可以sed从行号文件中生成一个简单的脚本。可以幽默地(但可能有些困惑)使用sed

sed 's%$%d%' linenumbers

这接受一个行号文件,每行一个,并在标准输出上产生相同的行号,并d在每行之后附加一个。这是一个有效的sed脚本,我们可以将其保存到文件中,或(在某些平台上)通过管道传输到另一个sed实例:

sed 's%$%d%' linenumbers | sed -f - logfile

在某些平台上,sed -f不明白的选项参数-是指标准输入,所以你必须在脚本重定向到一个临时文件,并清理完成后,或可能与更换孤独破折号/dev/stdin/proc/$pid/fd/1如果你的操作系统(或壳)具有该功能。

与往常一样,您可以-i-f选项之前添加以sed在适当位置编辑目标文件,而不是在标准输出上生成结果。在* BSDish平台(包括OSX)上,您还需要提供一个明确的参数-i。一个常见的成语是提供一个空的论点;-i ''


我不太同意“反模式的症状”。基于标记的文件类型(例如XML或JSON)在末尾需要特定的行才能成为有效文件。在这种情况下,这通常是最合理的方法,即删除这些行,将要添加的内容放入文件中,然后重新添加这些行,因为将这些行直接放在中间可能会更加费力,并且与尽可能避免使用sed这样的额外工具的潜在愿望。
Egor Hans,

我不太了解您在想哪种情况。在某些情况下,这是一种合法的方法,但是我看到的绝大多数案例都是新手,他们或多或少地完全按照我的第一个示例所展示的来做。(也许它们来自某种真正的底层语言,并且习惯于通过分子水平将问题划分出来,因为您必须使用asm或C。)
Tripleee '18

通过XML或JSON行号删除的东西听起来extermely脆,如果不是彻底的危险。
Tripleee '18

我的基本意思是,作为此类文件的创建者,您必须知道文档末尾的内容(例如,JSON的最后几行中的右括号/方括号的集合,或确切的XML的结束标记)。请注意,扩展此类文档的最简单方法是1)删除最后几行,2)添加新内容,3)重新添加最后几行。这样,文档可以在扩展之前和之后均有效,而无需找到在文档中间添加行的方法。
Egor Hans

1
到目前为止,这是针对大量行(即由文件提供)的适当解决方案的唯一答案。前言也很有意义。它值得更多的投票。顺便说一句,如果您要打印行而不是删除行,请使用p而不是d和选项一起使用-n(没有-n!d它将不起作用,也将不起作用)。
Skippy le Grand Gourou

2

我想提出awk的概括。

当文件由固定大小的块组成并且要删除的行在每个块中重复时,awk可以通过这种方式正常工作

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

在此示例中,该块的大小为2000,我要打印行[1..713]和[1026..1029]。

  • NR 是awk用于存储当前行号的变量。
  • % 给出两个整数除的余数(或模数);
  • nl=((NR-1)%BLOCKSIZE)+1在这里,我们在变量nl中写入当前块内的行号。(见下文)
  • ||并且&&是逻辑运算符ORAND
  • print $0 写完整行

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+


2
我很佩服您辜负疯狂的名字。
Jukka Dahlbom 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.