Delete trailing newline in Atom for existing files - regex

I have about 150 files that have an additional newline at the end which needs to be removed. I have set the 'Ensure trailing space' setting from the whitespace package in Atom, however it only works for new files. I need to apply it to existing files, since I cannot edit each file to delete the last line.
I have tried using a regex, but Atom selects all line breaks instead of just the last. \z doesn't seem to work, it simply selects all z characters.
Is there a regex that will help me select the very last newline in Atom? Or is there a way to apply the settings to existing files?

You may use
(?:\r\n?|\n)(?![\s\S])
Details
(?:\r\n?|\n) - a CRLF, CR or LF line break
(?![\s\S]) - not followed with any char.
Regex graph:

Related

Bug in Notepad++ / BOOST or bug in my regular expression?

I have a file which is structured like this:
Line
foo Änderbar: PM baz
Line
Line
foo Änderbar: OM baz
Line
Line
foo Änderbar: ++ baz
Line
Line
foo Änderbar: -- baz
Line
So the file consists of "blocks" which are separated by a newline (I have converted the file to Unix line endings). Each block can have an arbitrary number of lines. Each line of a block contains at least one character which is not a newline, and is finished by a newline character. The lines which separate the blocks consist of exactly one newline character.
In each block, there is exactly one line in the following format:
at least one character which is not newline, followed by
the literal string 'Änderbar: ', followed by
exactly one of the literal strings '++', '--', 'OM', 'PM', followed by
at least one character which is not newline, followed by
the line-terminating newline character
There is always at least one other non-empty line in the same block above this special line and one other non-empty line below this special line.
I need an effective method to find (and thereby select) all blocks where the literal after Änderbar: is -- (find / select one block after another, each one after hitting Find Next again, i.e. not selecting all of those blocks at the same time).
Normally, I have fun solving such problems with Notepad++. However, in that case, it seems that I either get more and more stupid as I get older, or that there is a bug in Notepad++'s regex handling engine.
Notepad++ uses BOOST (and supports PCRE expressions via BOOST). Since this is in wide use, I consider that problem important enough to post it here, just in case that BOOST really is the reason for the misbehavior.
Having said this: I loaded that file into Notepad++, fired up the Search and Replace dialog, ticked . matches newline, ticked Regular Expression and entered the following regex in the Find What: textbox:
\n([^\n]+\n)+[^\n]+(Änderbar\:\ --[^\n]+\n)([^\n]+\n)+
I was quite surprised that this made Notepad++ behave weirdly: When the cursor was placed in the empty line immediately before a block with Änderbar: --, hitting Find Next found / selected that block as expected. But when the cursor was at another place, hitting Find Next made Notepad++ find / select the whole rest of the file, i.e. all blocks below the cursor position.
I then have tested if it would find the blocks having ++ after Änderbar:, i.e. I changed my regex to
\n([^\n]+\n)+[^\n]+(Änderbar\:\ \+\+[^\n]+\n)([^\n]+\n)+
Guess what: This was working reliably in each situation. The same is true for the last both:
\n([^\n]+\n)+[^\n]+(Änderbar\:\ PM[^\n]+\n)([^\n]+\n)+
\n([^\n]+\n)+[^\n]+(Änderbar\:\ OM[^\n]+\n)([^\n]+\n)+
So Notepad++ / PCRE seems to have a problem with the correct interpretation of - under certain circumstances, or I have a subtle bug in my regex which only triggers when I am searching for -- (instead of ++, OM or PM) at the respective place.
Please note that I already have tried to leave away the \ in front of the space character (which actually could only make the situation worse, but I've tried just in case) and that I also have tried to use \-\- instead of -- (although the latter should be fine). That did not alter the (mis-)behavior in any way.
So what is the problem here? Is there a bug in my regex, or is there a bug in Notepad++?
UPDATE
I have stripped down the actual file in question and have uploaded it to https://pastebin.com/w62E57U5. To reproduce the problem, please do the following:
Download the file from the link above and save it somewhere on your HDD (do not copy the text directly into Notepad++).
Load the file into Notepad++. The cursor now is in the topmost line, and nothing is selected.
This is essential: Click Edit -> EOL Conversion -> Unix (LF).
Verify that the cursor is still in the topmost line (which is empty) and that nothing is selected.
Open the Find dialog and choose the settings and enter the search string as described above.
Click "Find Next".
Note that now the complete text is found / selected.
Keeping the Find window open, delete the third line of the file (it reads "Funktionspaket(e): ML"). Do not just empty that line, but really delete it so that no empty line remains between the line before and the line after.
Again, place the cursor in the topmost line (which is still empty) and make sure nothing is selected.
Click "Find Next".
Note that the regular expression now works as expected.
Obviously, somebody is trying to make a fool of me, right?
I think the key is: you need to begin your regex with ^ (beginning of line).
Your original regex becomes:
^\n([^\n]+\n)+[^\n]+(Änderbar\:\ --[^\n]+\n)([^\n]+\n)+
But you can simplify it with:
^\R(?:.+\R)+.+Änderbar: --.+\R(?:.+(?:\R|\z))+
Note: tick . matches newline
Where:
\R matches any kind of linebreak, no needs to change the EOL.
\z matches the end of file, if you don't use it, you can't match the last line of the file if there're no linebreak.
(?:...) is a non capture group, much more efficient (if you don't need to capture, of course)
Both works fine with your 2 sample files.
It's not a bug. You're just forgetting something very important - with Windows line endings, your lines have a \r before the \n, so the \n([^\n]+\n)+ part of your RegEx will also match your blank lines which is why clicking "Find Next" matches everything from the cursor position instead of from the start of the block.
Go to Edit > EOL Conversion > Unix (LF) and you'll see that it works now. If you want to support Windows and Unix line endings you'll have to change every [^\n] to [^\r\n] and every \n to \r?\n.

Regex: how to remove the last, empty line?

I want to remove the very last, empty line from a file using regex search-replace. Matching a new line with an end-of-line marker:
\n$
seem to be a step in a good direction, but it simply matches all empty lines (new lines character followed by an empty line, to be precise):
I'm using Sublime on Windows, if the line ending characters convention and regex engine does matter.
You can use \s*\Z to select all whiltespaces including newlines and \Z marks the end of input and replace it with empty string.
This will indeed get rid of all the newlines at the end of text (one or more) even when those newlines may contain spaces (not easily visible), which might be helpful, because in general we want to get rid of extra useless lines at the end of text in file.
Just in case if you want to get rid of ONLY ONE line from end of file, you can use \n\Z instead of \s*\Z.
Please check following screenshots demonstrating same.
Before replace,
After replace,
The following regex should help you achieve it
\n\s*$(?!\n)
It begins at line 6, and matches everything at line 7 and deletes it.
Basically it searches for the line that is empty and doesn't have a carriage return at the end
Demo 1
Look close, you'll see that line 7 has disappeared in the replacement
Demo 2 (in Visual Studio Code)
Before
After

Deleting lines with specific words in multiple files in Notepad++

I'm trying to removing a specific line from many files I'm working on with Notepad++.
Upon searching, I found Notepad++ Remove line with specific word in multiple files within a directory but somehow the regex provided (^.*(?:YOURSTRINGHERE).*\r\n$) from the answers doesn't work for me (screenshot: https://cdn.discordapp.com/attachments/311547963883388938/407737068475908096/unknown.png).
I read on some other questions/answers that certain regex doesn't work in newer/older Notepad++ versions. I was using Notepad++ 5.x.x then updated to the latest 7.5.4, but neither worked with the regex provided in the question above.
At the moment I can work around it by replacing that line with nothing, twice (because there are only 2 variants that I need to remove from those files) but that leaves an empty line at the end of the files. So I have to do another step further to remove that empty line.
I'm hoping someone can offer helps that allow me to remove that line and leave no empty line/space behind.
The regex you attempt to use will only match your line, if it is followed by an empty line and Windows linebreaks (CR LF) are used. This is due to \r\n$ which matches a linebreak sequence followed by the end of the line.
Instead you might want to use
^.*(?:YOURSTRINGHERE).*\R?
To match the line containing your string and optionally a following line break sequence to remove the line instead of emptying it out. This will leave you with a trailing newline, if your word is contained in the last line of a file. You can use
(\R)?.*(?:YOURSTRINGHERE).*(?(1)|\R)
To avoid this. It uses a conditional to either match the previous linebreak, or the following if there is none.

Line feed regular expression doesn't work in Geany

I want to detect line feed with Geany in Ubuntu. I used regular expressions such as \n , \r and \r\n, but it doesn't detect anything.
There are some line ending settings that I also try to change to make it work, but still no success:
And finally, I also tried to use different encoding from document → set encoding menu, but still no success.
I guess I am doing something wrong, but I still don't know what.
As Mohammad Yusuf Ghazi comments, you need to enable the Use multi-line matching option. See the Geany docs:
The Use multi-line matching dialog option enables multi-line regular expressions.
Multi-line regular expressions work just like single-line ones but a match can span several lines.
Besides, you may also use \R shorthand class for any line break sequence:
Newline sequences
Outside a character class, the escape sequence \R matches any Unicode newline sequence. This particular group matches either the two-character sequence CR followed by LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab, U+000B), FF (formfeed, U+000C), CR (carriage return, U+000D), NEL (next line, U+0085), LS (line separator, U+2028), or PS (paragraph separator, U+2029). The two-character sequence is treated as a single unit that cannot be split. Inside a character class, \R matches the letter "R".
In a simple search just within the open file, select from the end of the line to the beginning of the first line. Copy and paste in the find box.
It will be seen as a squarebox with four letters written inside. This will definitely detect each LF in Geany.
In regex, use $ instead of \r\n or \R. It will detect the end of line in multiline mode in Geany.

Regex to remove the first 2 lines of a text file

I am trying to delete only the first 2 lines of a text file.
I tried using \A.*, but this gets the first line and deletes the rest.
Is there a way to do the inverse?
It is maybe not the most convenient way, but it is possible with Regex:
^.*\n.*\n([\s\S]*)$
With default settings (neither single-line nor multi-line modifiers) the '.' captures everything, except newline. Therfore, .*\n captures one line, including the new line character. Repeat it twice, and we are at the beginning of the third line. Now capture all characters, including the new line character ([\s\S] is a nice workaround for this behavior) until the end of the file $.
Then substitute by the first capturing group
\1
and you have everything but the first 2 lines.
The details depend on your regex engine, how you give the substitute string. And depending on the platform or the used new line character of the file, you might need to exchange the \n with \r\n or \r or the one that matches it all (\r\n?|\n).
Here is a working Demo.