繁体   English   中英

使用sed删除特定行的Bash脚本不起作用

[英]Bash script using sed to delete specific line doesn't work

我试图编写一个bash脚本以使用sed删除文件的某些行。 行号以相反的顺序存储在另一个文件中。 我尝试执行的命令如下:

sed -e '{lineNumber}d' ./file.txt

这是我到目前为止的内容,但是没有用

while read -r line 
do 
   sed -e "/${line}d" ./file.txt
done < ./lineNum.txt

我收到以下错误:
sed:-e表达式#1,字符4:未终止的地址正则表达式

其实你做错了

sed -e "/${line}d" ./file.txt

您看, sed具有以下语法

sed -e "/REGEX/d" ./file.txt

删除包含与REGEX模式匹配的所有行。 由于您拥有第一个/ ,因此sed认为您正在尝试使用正则表达式匹配,因此它表示的是unterminated address regex

所需的最小修复方法是简单地删除有问题的反斜杠,即

sed -e "${line}d" ./file.txt

旁白 :不是像OP那样需要sed解决方案,而是OP想要的效率更高。

awk 'NR==FNR {arr[$0]++; next} {if (!arr[FNR]) print }' linenum.txt file.txt

只要没有太多要删除的行,并且您不在使用sed版本非常有限的系统上工作(一次,HP-UX上的sed限于大约100个命令),那么您可以采用:

sed 's/$/d/' linenum.txt | sed -f - file.txt

这将使用第一个sed将行号转换为删除命令(请注意,您的麻烦部分是多余的斜线),然后告诉第二个sed从标准输入( -f - )中读取其脚本并将其应用于file.txt

以上与GNU sed ; 它不与BSD工作sed在Mac OS X 10.7.5( sed: -: No such file or directory )。 在系统上使用它之前进行测试。

当然,如果您拥有最新版本的bash (可用于bash 4.2,但不适用于3.2),则可以使用“进程替换”来解决sed的局限性:

 sed -f <(sed 's/$/d/' linenum.txt) file.txt

如果这也不起作用,则可以将第一个sed命令的输出写入文件,然后使用该(临时)文件作为sed脚本的名称。 因此,有很多方法可以做到这一点。 但是,超过3个进程(两个sed运行和rm之一运行)的任何操作都是奢侈的。 如果您只需要执行一次,这可能不是问题,但是如果您必须每分钟执行多次,则可能会成为问题。

while read -r line; do sed -i "${line} d" ./file.txt; done < ./linenum.txt

这行得通(我认为您的问题是使用-e); 但是效率不高。 一次传递多行可能更好,以避免每行一次读写文件。 例如,您可以将linenum.txt转换为“ 6 d; 2 d; 1 d;”之类的内容。 然后将其传递给sed以进行一次独家处理。

您可以直接使用sed进行更改,而无需使用循环:

sed 's/.*/&d/' lineNum.txt | sed -i -f - file.txt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM