Home > Software engineering >  SED delete lines
SED delete lines

Time:01-07

I want to delete all lines from first to till last occurrence line of matching pattern "1055/Rack2.txt" including this line. This pattern occurred three times in below data. Here is the data where I want to work with.

/root/monitor_data/hmc_temp/2023-01-06-1050/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1050/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1055/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt

I tried with below command, but it deletes only from first line to first occurrence of matching pattern. Deletion not done for next two occurrence.

sed -i '1,/1055\/Rack2/d' input.txt

and leaves two lines with same matching pattern and the output is below.

/root/monitor_data/hmc_temp/2023-01-06-1055/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1100/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1105/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack0.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack1.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt
/root/monitor_data/hmc_temp/2023-01-06-1110/Rack2.txt```

CodePudding user response:

If ed is available/acceptable, something like:

printf '%b\n' '?1055\/Rack2?kx' "1;'xd" ,p Q | ed -s input.txt

A small explanation about the ed code.

  • ?pattern-goes-here? is the same as /pattern-goes-here/, only difference is the search starts from the last line of the buffer. The pattern is 1055/Rack2. Note the use of ? ? instead of / /.

  • kx Marks the line/string in the buffer, in this case whatever is matched by the ?pattern-goes-here?, k is the command and x is the marker.

  • 1;'xd Is an address range separated by a ; e.g. start;end The 1 is the line number, 'x is how to call/evaluate/expand the marked line/string with kx and d means delete.

  • So in the end it reads from line number 1, delete until it reaches the spot which is marked and x indeed marks the spot! ;-)

  • If in-place editing is required change Q to w

  • Remove the ,p to silence the output.

CodePudding user response:

Here's a solution for awk:

tac test | awk '/1055\/Rack2.txt/{f=1}!f' | tac

This command starts printing lines after last match of /1055\/Rack2.txt/.

CodePudding user response:

This might work for you (GNU sed):

sed 'H;/1055\/Rack2/{z;h};$!d;x;s/.//' file

Make a copy of the lines before 1055/Rack2 and replace those lines by a newline when the current line is 1055/Rack2. At the end of the file, remove the newline at the start of the copy and print the remaining lines.

Alternative:

sed -z 's#.*1055/Rack2[^\n]*\n##' file

The -z option slurps the whole file into memory. Since .* is greedy it will remove everything upto the last occurrence of 1055/Rack2. The [^\n]*\n removes to the end of that line.

  • Related