Use regex to analyze path in Makefile - regex

I need to do some replacement of the path in Makefile.
For example, I have a path like this
p := some/path/to/file
I would like to do the replacement of "p" to get this
../../../file
In other words, I'd like to replace the path to relative path. How can I use regex to do that in Makefile? Any comments would be appreciated. Thanks!

Depending on software/language you are using to edit just replace any word ending with "/" to ".../"
This way you will get your relative path. Live demo here.
For special characters you can wrap everything in [] and add special characters you are expecting, for example like this. Some need escaping with \, just give it a try on Regex101 to find out which ones.
If you also have digits in your filepath you need to add \d to the "pool": demo.

Related

Automatically slash the backslashes in vim

Can we write functions/subroutines in csh or vim?
Basically, my question is how to slash the backslashes inside a string automatically which we use for search in vim.
Lets say:
Contents of file file_a is:
abcd
a/b/c/d
Now, if I search 'abcd' inside vim with "/abcd" in command mode, it will match abcd(first line).
And If I search for 'a/b/c/d', it will not match whole of 'a/b/c/d'. It will match only 'a' from 'a/b/c/d'.
To match whole of 'a/b/c/d', I would need to search for a\/b\/c\/d. Slashing backslashes is a pain every time you want to search for strings having backslashes inside it. :)
Have anyone of you solved this earlier?
In Vim:
You can search backwards, where the separator is ? instead of /, so / does not need to be escaped: ?a/b/c/d; to move to the next match downwards, use N.
Or you can set the search pattern using :let #/="a/b/c/d" (this will not move the cursor), then use n to go the next match.
You can also define your own command:
function! FindSlashed(arg)
let #/=a:arg
norm n
endfunction
command! -nargs=1 S call FindSlashed(<q-args>)
which you can use like this:
:S a/b/c/d
EDIT: let, not set.
This is not about searching but about replacing. I thought you might find this helpful as you're writing functions
You can use alternate delimiters for replace command. ie, rather than using /, you can use something like #
:s#a/b/c/d#this text will replace#
The above command will replace a/b/c/d with this text will replace

How to catch all of the files under a path which doesn't have a specific extension and exclude subdirectories?

I have a folder/file structure as following:
/path2files/subfolder1
/path2files/abcd
/path2files/abcd.sh
/path2files/defg
/path2files/defg.sh
/path2files/logs
I want to have a regex that matches all files that do not have the .sh extension and exclude the subdirectories.
I cannot figure out an optimized regex to do it.
I got the following, which would match also the subdir:
/^((?!\.sh)^.)*$/
If anybody could help or at least put me in the right direction?
Note: The "/path2files/" could be "/path/2/files/".
Note2: Anything with a "." after the last "/" is a file.
This regex matches any file with an extension, except .sh.
.+(?=\.)(?!\.sh)(?!\..+\/)
Demo.
For a regex, there is no difference between a directory and a file if there isn't a special notation.
You could use the below regex to match all the file-names which have dot extension except the one which ends with .sh.
^.+\.(?!sh$)[^.\/]+$
DEMO

Regex to select path till a folder name

Given a string "C:\Tom\Dick\Harry\Chocolate\Treat\Hunt\Fruitless" I have to select anything which appears before Treat.
I have tried with
(.*)\\Treat
but it includes the Treat word also.
Result is "C:\Tom\Dick\Harry\Chocolate\Treat".
Any help will be much appreciated.
You could use a lookahead in the regex if you don't want to include the word \Treat.
.*(?=\\Treat)
DEMO
OR
If you want to include the word Treat then try the below regex,
^.*?\\Treat
DEMO
(.*?)(?:Treat).*
This simple re should do it.
See demo

Regex to parse file paths

I have this text:
Unexpected error creating debug information file
'c:\Users\Path1\Path2\Strategies\Path3\CustomStrategy.PDB' --
'c:\Users\Path1\Path2\Strategies\Path3\CustomStrategy.pdb: The system
cannot find the path specified.
I need to parse out the file paths c:\Users\Path1\Path2\Strategies\Path3 or c:\Users\Path1\Path2\Strategies\Path3\CustomStrategy.PDB, whatever is easier. I tried to use the following Regex
\w:.+[.]\w{3}
But, this RegEx doesn't stop at first file extension and continues to match the the second instance of the path, stopping at the second instance of .pdb; thus putting both file paths in one regex match.
What do I need to change in order for the regex to parse the two paths as two separate matches? Thanks.
Non-greedy re:
\w:.+?[.]\w{3}
Note ? after +.
Also, if your path contains no dots except the last one, you can write it so:
\w:[^.]+[.]\w{3}
If you are not sure that the extension consists of three letters, you must specify the range:
\w:[^.]+[.]\w{1,3}
And when you are not sure that your path has extension at all, but it contains no spaces, then:
\w:\S+
What about this
\w:\\(?:[^\\\s]+\\)+
See it here on Regexr
\w:\\ matches a word character, a : and a backslash
(?:[^\\\s]+\\)+ matches the directories, non-backslash or non whitespace characters till a backslash, and this repeated.
So, this would match both paths c:\Users\Path1\Path2\Strategies\Path3. works as long as the directory names does not contain spaces.
Actually, here you may as well do without regex at all.
Split the text by ' and use the second part.
As for regex, I would use something more complicated, but allowing to catch other filenames, not just those ending with a 3-letter extension:
'([a-z]:(?:[\\/][^\\/]*)+?)' --
(and use first subpattern from the match)

Adding "/index.html" to paths in Vim

I'm trying to append "/index.html" to some folder paths in a list like this:
path/one/
/another/index.html
other/file/index.html
path/number/two
this/is/the/third/path/
path/five
sixth/path/goes/here/
Obviously the text only needs to be added where it does not exist yet. I could achieve some good results with (vim command):
:%s/^\([^.]*\)$/\1\/index.html/
The only problem is that after running this command, some lines like the 1st, 5th and 7th in the previous example end up with duplicated slashes. That's easy to solve too, all I have to do is search for duplicates and replace with a single slashes.
But the question is:
Isn't there a better way to achieve the correct result at once?
I'm a Vim beginner, and not a regex master also. Any tips are really appreciated!
Thanks!
So very close :)
Just add an optional slash to the end of the regex:
\/\?
Then you need to change the rest of the pattern to a non-greedy match so that it ignores a trailing slash. The syntax for a non-greedy match in vim (replacing the *) is:
\{-}
So we end up with:
:%s/^\([^\.]\{-}\)\/\?$/\1\/index.html/
(Doesn't hurt to be safe and escape the period.)
Vim's regex supports the ability to match a bit of text foo if it does or doesn't precedes or follows some other text bar without matching bar, and this is exactly the sort of thing you're looking for. Here you want to match the end of line with an optional /, but only if the / isn't followed by index.html, and then replace it with /index.html. A quick look at Vim's help tells me \#<! is exactly what to use. It tells Vim that the preceding atom must be in the text but not in what's matched. With a little experimentation, I get
:%s;/\?\(index\.html\)\#<!$;/index.html;
I use ; to delimit the parts of the :s command so that I don't have to escape any / in the regex or replacement expression. In this particular situation, it's not a big deal though.
The / is optional, and we say so with \?.
We need to group index.html together because otherwise our special \#<! would only affect the l otherwise.