Issue
I am trying to remove lines from a text file that start with a particular string and does not contain a string.
For example I would like to simply delete all lines as below from a file. The below line starts with connect_bd_net and does not contain any text that is Clk or clock etc. Note that the line begins with a space
connect_bd_net -net aux_reset_in_1 [get_bd_pins hls_rstn] [get_bd_pins proc_sys_reset_1/aux_reset_in]
While at it I would like to not delete the following line
connect_bd_net -net rx_acr_aud_clk_out [get_bd_pins aud_clk_out_0] [get_bd_pins rx_acr/aud_clk_out]
Here are my attempt with sed
sed 's/^(.+connect_bd_net.+(?!\bcl.+k).)*$//g' input.tcl
sed '/^(.+connect_bd_net.+(?!\bcl.+k).)*$/d' input.tcl
Solution
sed
is a scripting language. It's slightly obscure, but it's not hard to learn the basics.
sed '/Clk\|clock/b;/^connect_bd_net/d' file >newfile
The first condition says to skip the rest of the script if the regex matches (the b
command says to branch, i.e. goto
, and the default destination is to branch to the end of the script). If that didn't trigger, we delete lines (d
) which match the second condition.
Your precise requirements are sightly unclear; if you want to add word boundaries to the regular expressions, you clearly already know how. However, your sed
almost certainly does not support Perl-style regex extensions like the (?!...)
lookaheads you were attempting (and without an -E
or -r
option, you have to backslash even rather basic regex metacharacters like parentheses and +
to not simply match them literally. This is arguably weird, but a sacrifice to backwards compatibility).
As a brief reminder, the overall processing model is to read one line at a time, and execute the script on that line, then repeat this for each following line in the input.
Going forward, you might prefer Awk, which is considerably more human-readable.
awk '!/Clk|clock/ && /^connect_bd_net/ { next } 1' file >newfile
... or Perl.
perl -ne 'print if /Clk|clock/ or not /^connect_bd_net/' file >newfile
By the by, the /g
flag you tried to use only makes sense if you expect multiple occurrences per input line, which obviously you don't when your regex attempts to match the entire line.
Answered By - tripleee Answer Checked By - Clifford M. (WPSolving Volunteer)