4

How can I remove a line with a specific word but keeping in mind: if another word is found, then don't delete the line. For example, I'm deleting a line having sup or gnd with :%s/.*sup.*//g or :%s/.*gnd.*//g, but it is also deleting some lines which is breaking breaking loop line as well.

I don't want to delete lines which have module in the same line as gnd or sup. Any idea how to conquer the line?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
CLEX420
  • 43
  • 2

2 Answers2

5

You could use:

:v/module/s/\v.*(sup|gnd).*//
  • :v/pattern/cmd runs cmd on the lines that do not match the pattern
  • \v turns on very-magic so that all the (, | characters are treated as regexp operator without the need to prefix them with \.

Note that it empties but otherwise doesn't remove the lines that contain sup or gnd. To remove them, since you can't nest g/v commands, you could use vim's negative look ahead regexp operator in one g command instead:

:g/\v^(.*module)@!.*(sup|gnd)/d
  • :g/pattern/cmd runs cmd on the lines the do match the pattern
  • (pattern)@! (with very-magic) matches with zero width if the pattern is not matched at that position, so ^(.*module)@! matches at the beginning of a line that doesn't contain module.

There's also the option of piping to sed or awk:

:%!sed -e /module/b -e /sup/d -e /gnd/d
  • /module/b branches off (and the line is printed) for lines that contain module.
  • for the lines that don't, we carry on with the next two commands that delete the line if it contains sup or gnd respectively.

or:

:%!awk '/sup|gnd/ && ! /module/'

If you wanted to find those files that need those lines removed and remove them, you'd probably want to skip vim and do the whole thing with text processing utilities. On a GNU system:

find . ! -name '*.back' -type f -size +3c -exec gawk '
  /sup|gnd/ && ! /module/ {printf "%s\0", FILENAME; nextfile}' '{}' + |
  xargs -r0 sed -i.back -e /module/b -e /sup/d -e /gnd/d

(here saving a backup of the original files as the-file.back, change -i.back to -i if you don't need the backup).

  • find finds the regular files whose name doesn't end in .back and whose size is at least 4 bytes (smaller ones can't possibly contain a line that contains sup or gnd (and the line delimiter)) and runs gawk with the paths of the corresponding files as arguments.
  • when gawk finds a line in any of those files that match, it prints the path of the file (FILENAME special variable) delimited with a NUL character (for xargs -0) and skips to the next file.
  • xargs -r0 processes that gawk outputs to run sed with those file paths as arguments.
  • sed edits the file in place.
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • I've tried in the linux with grep -r "sup" | grep -vE "^module" | I've list of line but I can't use/find suitable command after 2nd pipe How to process after pipe, because after second I've list line which has sup but exclude module line, but I am not able to delete to those line from the file... – CLEX420 May 01 '18 at 06:57
  • @CLEX420, see edit. – Stéphane Chazelas May 01 '18 at 07:34
  • Why it is saying "find: missing argument to `-exec'" while using find command solution you gave – CLEX420 May 01 '18 at 08:06
  • @CLEX420, sorry my bad, I forgot the {} +. See edit (I still haven't tested it). – Stéphane Chazelas May 01 '18 at 08:07
  • It says: ------------ find . ! -name '*.back' -type f -size +3c -exec gawk '/sup/ && ! /module/ {printf "%s\0", cfg_pmc_por_top.v; nextfile}' '{}' + | xargs -r0 sed -i.bak -e /module/b -e /sup/d ------------------- gawk: /sup/ && ! /module/ {printf "%s\0", cfg_pmc_por_top.v; nextfile} gawk: ^ syntax error – CLEX420 May 01 '18 at 08:10
  • Your very first command did the job, but I want to lean how did you make this syntax or when can i learn these switches? – CLEX420 May 01 '18 at 08:11
  • @CLEX420, it has to be literal `FILENAME`, which gawk replaces with the name of the current file. – Stéphane Chazelas May 01 '18 at 08:14
  • See `info gawk`, `info find`, `info xargs`, `info sed` for details. For `vim`, see the `:help` command (`:h :g`, `:h :v`, `:h pattern.txt`) – Stéphane Chazelas May 01 '18 at 08:16
  • Is is not possible to pipe few more words with module :v/module/s/\v.*(sup|gnd).*// for here, like if I want to add input or output & remove all lines except module/input/output? – CLEX420 May 02 '18 at 05:49
  • You can do `:v/module\|input\|output/s/...//` or again use `\v` to avoid having to enter those backslashes: `:v/\vmodule|(in|out)put/s/...//`. See `:h pattern.txt` for details on vim's regexp syntax. – Stéphane Chazelas May 02 '18 at 08:33
0

Found it as :v/(module\|input\|output)/s/\v../

CLEX420
  • 43
  • 2