Emacs: How to delete a line starting with specific text - search

How can I find and delete lines which start with the text in?
I use the command C-M-s ^in to find all lines starting with in, but then I don't really know what to do.

M-x flush-lines RET ^in RET
C-h f flush-lines tells you:
flush-lines is an interactive compiled Lisp function in replace.el.
It is bound to menu-bar edit flush-lines.
(flush-lines REGEXP &optional RSTART REND INTERACTIVE)
Delete lines containing matches for REGEXP.
When called from Lisp (and usually when called interactively as
well, see below), applies to the part of the buffer after point.
The line point is in is deleted if and only if it contains a
match for regexp starting after point.
If REGEXP contains upper case characters (excluding those preceded by \)
and search-upper-case is non-nil, the matching is case-sensitive.
Second and third arg RSTART and REND specify the region to operate on.
Lines partially contained in this region are deleted if and only if
they contain a match entirely contained in it.
Interactively, in Transient Mark mode when the mark is active, operate
on the contents of the region. Otherwise, operate from point to the
end of (the accessible portion of) the buffer. When calling this function
from Lisp, you can pretend that it was called interactively by passing
a non-nil INTERACTIVE argument.
If a match is split across lines, all the lines it lies in are deleted.
They are deleted before looking for the next match. Hence, a match
starting on the same line at which another match ended is ignored.

query-replace-regexp "in.*" to "" will be work. you should not input " to the prompt

Related

Highlight empty lines at beginning and end of file and more than one empty lines

In vim, I would like to highlight empty lines at beginning and end of file, and more than one consecutive line. Example:
--- start of file
.
an empty line just before this line (at the beginning of the file)
more than one empty line will follow
.
.
empty lines at the end of file will follow
.
.
--- end of file
In the example above, the lines with a dot should be highlighted.
I've tried to match the lines with the following expression, unfortunately without luck:
call matchadd('EmptyLines', '\n\s\*\n\s\*\n')
How can I match all of these lines and highlight them (preferably the whole line)?
The special regular expression atoms \%^ (:help start-of-file) and \%$ (:help end-of-file) will help here. With them, you can match empty lines at the boundaries of the buffer, like this:
call matchadd('EmptyLines', '\%^\n\+')
call matchadd('EmptyLines', '^\n\+\%$')
Unfortunately, there are some limitations:
You can only match what's there, which is not much in empty lines. Vim will just highlight a single cell width (that represents the newline character).
In the very last line, nothing is highlighted at all. If you want to see any indication of a single empty final line, you could drop the ^ from the pattern. Then, the empty trailing line would be indicated by highlighting before that line.
Implementation alternatives
Using :help signs, you can highlight the full width of empty lines, and have an additional indication in the sign column. The downside is that you can't simply define a pattern for signs. You have to explicitly place them on certain lines, and adapt this position whenever the buffer contents change. That would mean defining some :autocmds, and living with either poor performance or accepting short delays until the signs update. (They are meant to be used for things like marking build errors that don't change so often and only on demand.)
Instead of a visual indication, if your goal is to avoid having those empty lines, you could also hook into the BufWrite event and either print a warning or completely abort the :write if such lines are found. My DeleteTrailingWhitespace plugin does this (but for whitespace at the end of individual lines).

How to find and remove part of word in vim?

I'm new into vim, I have hug text file as follow:
ZK792.6,ZK792.6(let-60),cel-miR-62(18),0.239
UTR3,IV:11688688-11688716,0.0670782
ZC449.3b,ZC449.3(ZC449.3),cel-miR-62(18),0.514
UTR3,X:5020692-5020720,0.355907
First, I would like to get delete all rows with even numbers (2,4,6...).
Second, I would like to remove (18) from entire file. as a example:
cel-miR-62(18) would be cel-miR-62.
Third: How can I get delete all parentheses including it's inside?
Would someone help me with this?
For the first one:
:g/[02468]\>/d
where :g matches all lines by the regex between the slashes and runs d (delete line) on the matching lines. The regex is quite easy to read, the only interesting symbol there is perhaps the \>, which matches end of a word.
For the second question:
:%s/\V(18)//g
where % is the specification meaning "all lines of the file", s is the substitute command, \V sets the "very nomagic" mode of regexes (not sure what your default is, you might not need this) and the final g makes vim substitute all occurrences on each line (with an empty string, the one between slashes). Make sure that :set gdefault? prints nogdefault (the default setting of gdefault), otherwise, drop the final g from the substitute command.
To remove every even line (or every other line):
:g/^/+d
To remove every instance of (18):
:%s/(18)//g
Remove all the parenthetical content:
:%s/(.\\{-})//g
Note: the pattern in third answer is a non-greedy match.

Vim: delete until character for all lines containing a pattern

I'm learning the power of g and want to delete all lines containing an expression, to the end of the sentence (marked by a period). Like so:
There was a little sheep. The sheep was black. There was another sheep.
(Run command to find all sentences like There was and delete to the next period).
The sheep was black.
I've tried:
:g/There was/d\/\. in an attempt to "delete forward until the next period" but I get a trailing characters error.
:g/There was/df. but get a df. is not an editor command error.
Any thoughts?
The action associated with g must be able to act on the line without needing position information from the pattern match that g implies. In the command you are using, the delete forward command needs a starting position that is not being provided.
The problem is that g only indicates a line match, not a specific character position for it's pattern match. I did the following and it did what I think you want:
:g/There was/s/There was[^.]*[.]//
This found lines that matched the pattern There was, and performed a substitution of the regular expression There was[^.]*[.] with the empty string.
This is equivalent to:
:1,$s/There was[^.]*[.]//g
I'm not sure what the g is getting you in your use case, except the automatic application to the entire file line range (same as 1,$ or %). The g in this latter example has to do with applying the substitution to all patterns on the same line, not with the range of lines affected by the substitution command.
I'd just use a regex:
%s/There was\_.\{-}\.\s\?//ge
Note how \_. allows for cross-line sentences
You can use :norm like this:
:g/There was/norm 0weldf.
This finds lines with "There was" then executes the normal commands 0weldf..
0: go to beginning of line
w: go to next word (in this case, "was")
e: go the end of the word (so cursor is on the 's' of "was")
l: move one character to the right (so we don't delete any of "was")
df.: delete until the next '.', inclusive.
If you want to keep the period use dt. instead of df..
If you don't want to delete from the beginning of the line and instead want to do sentences, the :%s command is probably more appropriate here. (e.g. :%s/\(There was\)[^.]*\./\1/g or %s/\(There was\)[^.]*\./\1./g if you want to keep the period at the end of the sentence.
Use search and replace:
:%s/There was[^.]*\.\s*//g

How to do something in a function based on the character under the cursor in Vim?

I’m writing a function that edits a certain environment in LaTeX.
The environment basically looks like this:
\begin{quicktikz}
...some stuff...
\end{quicktikz}
or like this:
\begin*{quicktikz}
...some stuff...
\end{quicktikz}
I want to write a function that toggles between the two, when called from within the environment. Since my Vim knowledge ain’t all that, I’m coming up with a simple solution:
Get cursor position with let save_cursor=getpos(".").
Backward search for \begin{quicktikz} using: ?\\begin{quicktikz}\|\\begin\*{quicktikz}.
Search for the { and move left using: normal 0f{h.
Check if the item under cursor equals *:
if it does, do normal x;
if it doesn’t, do normal a*<esc>.
Restore cursor position using call setpos('.',save_cursor).
I know how to do all of this except for step 3. How can I check if the char under the cursor equals to * or not?
If you know a better way of doing this, sharing this would be welcome.
I think the easiest way to retrieve the char under cursor is:
getline(".")[col(".")-1]
Alternatively, you can do it with strpart()
strpart(getline("."), col(".")-1, 1)
The first expression first calls the function getline() passing "." as
argument which means the line where the cursor is positioned will be returned.
Then we use the so called expr8 or expr-[] (see the help) to retrieve a
single character. The number passed comes from another function, col()
which returns the current cursor column. As indexes start in 0, one is subtracted.
You can use it like
if getline(".")[col(".")-1] == '*'
...
Let me propose an alternative implementation of the technique you describe.
:?\\begin\>\zs\*\=?s//\='*'[submatch(0)!='']/|norm!``
The above command consists of two separate commands chained with | (see
:help :bar) in one line. The first one is a substitution (see :help :s)
performed for each line in the specified range,
?\\begin\>\zs\*\=?
According to the range syntax (see :help :range), this range specifies the
only line, that is the previous line where the \\begin\>\zs\*\= pattern
matches the word begin preceded with a backslash and followed by by optional
star character.1 The \zs atom between parts of the pattern
matching \begin and *, sets the start of the match there. So, the match
of the whole pattern is either empty or contains single star character. This
is not necessary for specifying a line in the range, it is useful for reusing
the same pattern later in the :substitute command, where only that star
character or its empty place should be replaced. For details about the
pattern's syntax see :help /\>, :help /\=, :help /\zs.
The substitution itself,
s//\='*'[submatch(0)!='']/
replaces the first occurrence of the last search pattern (which is set by the
backward search in the range) with a string to which the expression
'*'[submatch(0)!=''] evaluates (see :help sub-replace-\=). As the pattern
matches only an empty string or a star character, the subexpression
submatch(0)!='' evaluates to zero if there is no star after \begin, or to
one otherwise. Zero subscript from the string '*' results in a substring
containing the first character of that one-character string. Index one is
equal to the length of the string, therefore subscript results in an empty
string. Thus, when there is a star after \begin, it gets replaced with an
empty string, when a star is not present, zero-width interval just after
\begin is substituted with *.
The second command,
:norm!``
takes advantage of the fact that :substitute command stores the current
cursor position before it actually starts replacement. The `` movement
command jumps back to the position before the latest jump (which occurs in the
aforementioned substitution command) restoring position of the
cursor.2
1 Be careful with search, since in ranges, as usual, it wraps
around the end of file, when the wrapscan option is enabled (it is turned on
by default).
2 Do not confuse `` with the '' command which moves the
cursor to the first non-blank character in the line of the location before the
latest jump.

Find first non-matching line in VIM

It happens sometimes that I have to look into various log and trace files on Windows and generally I use for the purpose VIM.
My problem though is that I still can't find any analog of grep -v inside of VIM: find in the buffer a line not matching given regular expression. E.g. log file is filled with lines which somewhere in a middle contain phrase all is ok and I need to find first line which doesn't contain all is ok.
I can write a custom function for that, yet at the moment that seems to be an overkill and likely to be slower than a native solution.
Is there any easy way to do it in VIM?
I believe if you simply want to have your cursor end up at the first non-matching line you can use visual as the command in your global command. So:
:v/pattern/visual
will leave your cursor at the first non-matching line. Or:
:g/pattern/visual
will leave your cursor at the first matching line.
you can use negative look-behind operator #<!
e.g. to find all lines not containing "a", use /\v^.+(^.*a.*$)#<!$
(\v just causes some operators like ( and #<! not to must have been backslash escaped)
the simpler method is to delete all lines matching or not matching the pattern (:g/PATTERN/d or :g!/PATTERN/d respectively)
I'm often in your case, so to "clean" the logs files I use :
:g/all is ok/d
Your grep -v can be achieved with
:v/error/d
Which will remove all lines which does not contain error.
It's probably already too late, but I think that this should be said somewhere.
Vim (since version about 7.4) comes with a plugin called LogiPat, which makes searching for lines which don't contain some string really easy. So using this plugin finding the lines not containing all is ok is done like this:
:LogiPat !"all is ok"
And then you can jump between the matching (or in this case not matching) lines with n and N.
You can also use logical operations like & and | to join different strings in one pattern:
:LP !("foo"|"bar")&"baz"
LP is shorthand for LogiPat, and this command will search for lines that contain the word baz and don't contain neither foo nor bar.
I just managed a somewhat klutzy procedure using the "g" command:
:%g!/search/p
This says to print out the non-matching lines... not sure if that worked, but it did end up with the cursor positioned on the first non-matching line.
(substitute some other string for "search", of course)
You can search with following line and press n to jump to the first non-matching line
^\(.*all is ok\)\#!.*$
Breakdown of operators:
^ -> means start of the line
\( and \) -> To match a whole string multiple times, it must be grouped into one item. This is done by putting "\(" before it and "\)" after it.
\#! -> Matches with zero width if the preceding atom does NOT match at the current position.
.* -> Matches any character repeated 1 or more times
$ -> end of the line
Here is sample animation how it works. For simplicity I searched for word apple.
You can iterate through the non-matches using g and a null substitution:
:g!/pattern/s/^//c
If you reply "n" each time you wont even mark the file as changed.
You need ctrl-C to escape from the circle (or keep going to bottom of file).

Resources