Delete specific line number(s) from a text file using sed?
我想从文件中删除一个或多个特定的行号。 我怎么用sed这样做?
-
你能给出你想要的更具体的例子吗? 您将如何决定删除哪些行?
-
根据行号
-
也许请参阅stackoverflow.com/questions/13272717/… 并且只是反向应用(如果键不在关联数组中则打印)。
如果要删除第5行到第10行和第12行:
这会将结果打印到屏幕上。如果要将结果保存到同一文件:
1
| sed -i.bak -e '5,10d;12d' file |
这会将文件备份到file.bak,并删除给定的行。
注意:行号从1开始。文件的第一行是1,而不是0。
-
并非所有的unix都有"-i"的gnu sed。不要错误地回到"sed cmd file> file",这会消灭你的文件。
-
如果我想删除第5行直到最后一行?
-
@WearetheWorld sed -e '5,$d' file
-
@BrianCampbell我该怎么做才能删除一个特定的行?
-
@KanagaveluSugumar sed -e '5d' file。语法是;其中可以是像5这样的单行,也可以是像5,10这样的行范围,命令d可以删除给定的一行或多行。地址也可以是正则表达式,或美元符号$表示文件的最后一行。
-
请注意,从5到10的行都包括在内。
-
我正在尝试使用bash脚本执行此操作,其中我计算要动态删除的行并将其存储在变量中。要删除的行数存储在变量$ rows_per_file中,但是当我向其添加d时,它当然会失败。关于如何实现这一点的任何建议,所以d被单独处理,而不是将它连接到变量。"sed -i -e 2,$ rows_per_filed $ 2"
您可以删除特定的单行及其行号
sed -i'33d'文件
这将删除33行号上的行并保存更新的文件。
-
在我的情况下,"sed"删除了错误的行。所以我使用这种方法:sed -i '0,//{//d;}' ''。谢谢!
-
同样在这里,我写了一个循环,奇怪的是一些文件丢失了正确的行,但一些文件也失去了另一行,不知道出了什么问题。 (GNU / Linux bash4.2)下面的awk命令在循环中运行良好
-
如果要从行列表中删除,请务必使用sort -r,否则您的第一个sed将更改其他所有内容的行号!...
-
使用-i,您可以从文件中永久删除
-
关于在循环中删除错误行的注释:请务必从最大行号开始,否则每个删除行将抵消行号...
和awk一样
1
| awk 'NR!~/^(5|10|25)$/' file |
-
注意:awk系列对我来说比sed变种更可靠(在OS-X和Ubuntu Linux之间)
-
请注意,这不会删除文件中的任何内容。它只是将没有这些行的文件打印到stdout。因此,您还需要将输出重定向到临时文件,然后移动临时文件以替换原始文件。
1 2 3 4 5 6 7 8 9 10 11
| $ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ |
这通常是反模式的症状。产生行号的工具很可能被替换为立即删除行的工具。例如;
1
| grep -nh error logfile | cut -d: -f1 | deletelines logfile |
(其中deletelines是您想象中所需的实用程序)与之相同
话虽如此,如果您确实需要执行此任务,可以从行号文件生成一个简单的sed脚本。幽默(但也许有点令人困惑)你可以用sed做到这一点。
1
| sed 's%$%d%' linenumbers |
这将接受一个行号文件,每行一个,并在标准输出上生成相同的行号,每行后附加d。这是一个有效的sed脚本,我们可以将其保存到文件中,或者(在某些平台上)管道到另一个sed实例:
1
| sed 's%$%d%' linenumbers | sed -f - logfile |
在某些平台上,sed -f不理解选项参数-表示标准输入,因此您必须将脚本重定向到临时文件,并在完成后将其清理,或者用<替换单独的短划线x15>或/proc/$pid/fd/1如果您的操作系统(或shell)具有此功能。
与往常一样,您可以在-f选项之前添加-i,以便sed编辑目标文件,而不是在标准输出上生成结果。在* BSDish平台(包括OSX)上,您还需要为-i提供显式参数;一个常见的习语就是提供一个空洞的论点; -i ''。
-
我不太同意"反模式的症状"。基于标记的文件类型(例如XML或JSON)最后需要特定的行才能成为有效文件。在这种情况下,删除这些行通常是最合理的方法,将要添加的文件放入文件然后重新添加这些行,因为直接将行放在两者之间可能会更加努力,并且反对尽可能避免像sed这样的额外工具的潜在愿望。
-
我不太明白你想象的是什么样的场景。在某些情况下,这是一种合法的方法,但我见过的绝大多数情况都是新手,他们或多或少地与我的第一个例子所展示的完全相同。 (也许它们来自一些非常低级的语言,习惯于将问题分解为超出分子水平,因为你必须在asm或C.)
-
通过XML或JSON中的行号删除内容听起来非常脆弱,即使不是完全危险的。
-
基本上我的意思是,作为这样一个文件的创建者,你知道文档末尾必须有什么(即JSON的最后几行中的结束括号/方括号的集合,或者确切的关闭XML的标签)。意识到这一点,扩展这样一个文档最简单的方法是1)删除最后几行,2)添加新内容,3)重新添加最后几行。这样,文档在扩展之前和之后都可以是有效的,而无需在文档中找到添加行的方法。
-
@EgorHans你仍然通常不知道或不关心那些线占用的线号。通过正则表达式删除它们更可能是正确的,也更有效;虽然大多数时候,你应该使用一个可以正确处理结构化格式错综复杂的工具(jq在JSON中很流行; xmlstarlet,xsltproc,xmllint,xpath等可用于XML)。
-
通常它们是file_line_amount - n到file_line_amount,其中n是从基于上下文的结构规范中得知的(例如,在许多情况下,标签内容的嵌套被添加到罐中,可以直线或几乎直线地用作n) 。我同意,基于正则表达式的方法或专用工具只是为了可读性和良好实践而更好。
-
到目前为止,这是对大量行(即由文件提供)的适当解决方案的唯一答案。前言也是有道理的。它值得更多的赞成。顺便说一句,如果你想打印行而不是删除它们,使用p而不是d,以及选项-n(没有-n它将无法工作,!d也无法工作) 。
我想用awk提出一个概括。
当文件由固定大小的块构成时
并且每个块重复要删除的行,
awk可以这样的方式正常工作
1 2
| 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中写入当前块内的行号。 (见下文)
-
||和&&是逻辑运算符OR和AND。
-
print $0写完整行
1 2 3 4 5 6 7 8 9 10 11 12
| 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 |
+-----+------+----------+------------+ |