Linux 命令在文件中搜索以字符串开头且没有字符串的行

Linux command to search for a line in a file what starts with a string and does not have a string

我正在尝试从文本文件中删除以特定字符串开头但不包含字符串的行。

例如,我想简单地从文件中删除以下所有行。 下面的行以 connect_bd_net 开头,不包含任何 Clk 或时钟等文本。请注意,该行以 space

开头
connect_bd_net -net aux_reset_in_1 [get_bd_pins hls_rstn] [get_bd_pins proc_sys_reset_1/aux_reset_in]

虽然我不想删除以下行

connect_bd_net -net rx_acr_aud_clk_out [get_bd_pins aud_clk_out_0] [get_bd_pins rx_acr/aud_clk_out]

这是我对 sed 的尝试

sed 's/^(.+connect_bd_net.+(?!\bcl.+k).)*$//g' input.tcl  
sed '/^(.+connect_bd_net.+(?!\bcl.+k).)*$/d' input.tcl

sed 是一种脚本语言。略显晦涩,但学好基础不难

sed '/Clk\|clock/b;/^connect_bd_net/d' file >newfile

第一个条件表示如果正则表达式匹配则跳过脚本的其余部分(b 命令表示分支,即 goto,默认目标是分支到末尾剧本)。如果没有触发,我们删除符合第二个条件的行 (d)。

您的具体要求有点不清楚;如果你想给正则表达式添加单词边界,你显然已经知道怎么做了。但是,您的 sed 几乎肯定不支持 Perl 样式的正则表达式扩展,例如您尝试的 (?!...) 前瞻(并且没有 -E-r 选项,您必须反斜杠甚至是基本的正则表达式元字符,如括号和 +,而不是简单地按字面匹配它们。这可以说是奇怪的,但却是对向后兼容性的牺牲。

作为一个简短的提醒,整体处理模型是一次读取一行,并在该行执行脚本,然后对输入中的每一行重复此操作。

展望未来,您可能更喜欢 Awk,它更易于阅读。

awk '!/Clk|clock/ && /^connect_bd_net/ { next } 1' file >newfile

... 或 Perl。

perl -ne 'print if /Clk|clock/ or not /^connect_bd_net/' file >newfile

顺便说一下,您尝试使用的 /g 标志只有在您希望每个输入行多次出现时才有意义,而当您的正则表达式试图匹配整行时,您显然不会这样做。

显示所有没有 connect_bd_net 的行(通过打印所有与 !p 不匹配的行)和两个匹配的行

sed -rn '/connect_bd_net/!p; /connect_bd_net.*(clock|Clk)/p' input.tcl  

这可能适合您 (GNU sed):

sed '/^connect_bd_net/{/clock\|Clk/!d}' file

如果某行以 connect_bd_net 开头且不包含 clockClk,则将其删除。