What is "map" matching exactly in Rack? - ruby-on-rails

Say I have this in Rack:
map '/great' do
run Test.new
end
This URL works great: site.com/great/stuff but this does NOT: site.com/greatstuff. I've read that map should match anything that STARTS WITH the the arg name, but this doesn't seem to be the case, with cases like these.
Is there any detailed specification on how this works?

The confusion seems to be conceptual.
It does match paths starting with /great. That is /great, /great/, /great/stuff and so on.
What it doesn't do is match strings starting with /great. Like /greatstuff.
/greatstuff and /greatare completely different paths. Think of paths as a tree structure.
There is no way to do "string path matching" with barebones map AFAIK, but you could add your own rack middleware that looks at the request path and dispatches appropriately.
If you want to double check the implementation, here are the two relevant places: 1, 2.
Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
This basically creates a regex out of a path that requires a string to start with that path (multiple / ignored) in order to match. Aka:
to_regex('/foo/bar') # => /^\/+foo\/+bar(.*)/n
In case you are wondering, the n flag sets the encoding to ASCII.
If the string matches, a few more checks are performed. Namely that the remainder of the matched path is either non-existent or starts with /. The latter ensures that you won't match things like /greatstuff with /great, as stuff doesn't start with /.
next unless !rest || rest.empty? || rest[0] == ?/

Related

What Lua pattern behaves like a regex negative lookahead?

my problem is I need to write a Lua code to interpret a text file and match lines with a pattern like
if line_str:match(myPattern) then do myAction(arg) end
Let's say I want a pattern to match lines containing "hello" in any context except one containing "hello world". I found that in regex, what I want is called negative lookahead, and you would write it like
.*hello (?!world).*
but I'm struggling to find the Lua version of this.
Let's say I want a pattern to match lines containing "hello" in any context except one containing "hello world".
As Wiktor has correctly pointed out, the simplest way to write this would be line:find"hello" and not line:find"hello world" (you can use both find and match here, but find is probably more performant; you can also turn off pattern matching for find).
I found that in regex, what I want is called negative lookahead, and
you would write it like .*hello (?!world).*
That's incorrect. If you checked against the existence of such a match, all it would tell you would be that there exists a "hello" which is not followed by a "world". The string hello hello world would match this, despite containing "hello world".
Negative lookahead is a questionable feature anyways as it isn't trivially provided by actually regular expressions and thus may not be implemented in linear time.
If you really need it, look into LPeg; negative lookahead is implemented as pattern1 - pattern2 there.
Finally, the RegEx may be translated to "just Lua" simply by searching for (1) the pattern without the negative part (2) the pattern with the negative part and checking whether there is a match in (1) that is not in (2) simply by counting:
local hello_count = 0; for _ in line:gmatch"hello" do hello_count = hello_count + 1 end
local helloworld_count = 0; for _ in line:gmatch"helloworld" do helloworld_count = helloworld_count + 1 end
if hello_count > helloworld_count then
-- there is a "hello" not followed by a "world"
end

Why we are unable to evaluate comprehension if we have defined it inside a rule body in OPA?

The following is my sample code: https://play.openpolicyagent.org/p/oyY1GOsYaf
Here when I try to evaluate names array, it is showing:
error occurred: 1:1: rego_unsafe_var_error: var names is unsafe
But when I define the same comprehension outside the allow rule definition : https://play.openpolicyagent.org/p/Xv0cF7FM8b, I am able to evaluate the selection
[
"smoke",
"dev"]
could someone help me to point out the difference and if I want to define the comprehention inside the rule is there any syntax I need to follow? Thanks in advance
Note: I am getting the final output as expected in both cases, only issue is with the names array evaluation.
The way the Rego Playground generates a query when evaluating a selection is much more simplistic than one might assume. A query will be generated from your selected text, without taking into account where in the document that text was selected. This means that even if you select a local variable inside a rule body, the query will simply contain that variable name (names, in your case); which will be perceived as a reference to a top-level variable in the document's body, even though a rule-local variable was selected. This is why your first sample returns an error, as there is no top-level variable names in the document; whereas the second sample does, and therefore succeeds.
You can test this quirk by selecting and evaluating the word hello on line 3 here: https://play.openpolicyagent.org/p/n5OPoFnlhx.
package play
# hello
hello {
m := input.message
m == "world"
}
Even though it's just part of a comment, it'll evaluate just as if you had selected the rule name on line 5.

how to call the deepest parentheses python

I'm trying to do this example :
sentence="{My name is {Adam} and I don't work here}"
Result should be 'Adam'
So what I'm trying to say is however many parenthesis exist I want the result to show the value of the last closed parenthesis
It's not clear from your question, but if there can only ever be one set of outer braces at any level (i.e. "{My name} {is {Adam}}" and "{My {name} is {Adam}}" are invalid input), you can take advantage of the fact that what you want is the last opening brace in the sentence.
def deepest(sentence):
intermediate = sentence.rpartition("{")[-1]
return intermediate[:intermediate.index("}")]
deepest("{My name is {Adam} and I don't work here}")
# 'Adam'
deepest("{Someone {set us {{up} the bomb}!}}")
# 'up'
The regex answer also makes this assumption, though regex is likely to be much slower. If multiple outer braces are possible, please make your question clearer.
You can't just index strings like that... The best way is to use a clever regex:
>>> import re
>>> re.search(r'{[^{}]*}', "{My name is {Adam} and I don't work here}").group()
'{Adam}'
This regex pattern essentially searches for every set of {} that doesn't have the characters { or } in them.

Searching for files with a specific pattern

I'm trying to look for specific files in a directory using a pattern
Lets say i have the id of the user - 101
here are my files
101
101_2
101_5
10111
103
10125
101_6
I'm trying to form a regex pattern which only gives me files (101,101_2,101_5,101_6)
I'm trying the below pattern
^101_?\d+$
but it doesnt seem to pick any of the files at all. if i remove the ^.only 101_6 matches for some reason.
EDIT:
I'm using rails/ruby to look for files in the particular directory. so something like
Dir.glob(location).grep("^101_?\d+$")
do something
end
If location isn't the current folder, paths returned by glob will contain dirname and basename :
Dir.glob('./*').select{ |f| File.basename(f) =~ /\A101(_\d+)?\z/ }.each do |f|
puts f
# do something with f
end
Your question isn't particularly clear, but I'm guessing you want to match anything which is 101 followed by an optional underscore and a digit. If so, use the regex ^101_?\d$. If you want 101 followed by either a digit or an underscore and one or more digits, use ^101(_\d+|\d)$
EDIT
As the OP has mentioned in a comment, 101 should also be matched. The updated regex is ^101(?:_?\d)?$

Matching function in erlang based on string format

I have user information coming in from an outside source and I need to check if that user is active. Sometimes I have a User and a Server and other times I have User#Server. The former case is no problem, I just have:
active(User, Server) ->
do whatever.
What I would like to do with the User#Server case is something like:
active([User, "#", Server]) ->
active(User, Server).
Doesn't seem to work. When calling active in the erlang terminal with a#b for example, I get an error that there is no match. Any help would be appreciated!
You can tokenize the string to get the result:
active(UserString) ->
[User,Server] = string:tokens(UserString,"#"),
active(User,Server).
If you need something more elaborate, or with better handling of something like email addresses, it might then be time to delve into using regular expressions with the re module.
active(UserString) ->
RegEx = "^([\\w\\.-]+)#([\\w\\.-]+)$",
{match, [User,Server]} = re:run(UserString,RegEx,[{capture,all_but_first,list}]),
active(User,Server).
Note: The supplied Regex is hardly sufficient for email address validation, it's just an example that allows all alphanumeric characters including underscores (\\w), dots (\\.), and dashes (-) seperated by an at symbol. And it will fail if the match doesn't stretch the whole length of the string: (^ to $).
A note on the pattern matching, for the real solution to your problem I think #chops suggestions should be used.
When matching patterns against strings I think it's useful to keep in mind that erlang strings are really lists of integers. So the string "#" is actually the same as [64] (64 being the ascii code for #)
This means that you match pattern [User, "#", Server] will match lists like: [97,[64],98], but not "a#b" (which in list form is [97,64,98]).
To match the string you need to do [User,$#,Server]. The $ operator gives you the ascii value of the character.
However this match pattern limits the matching string to be 1 character followed by # and then one more character...
It can be improved by doing [User, $# | Server] which allows the server part to have arbitrary length, but the User variable will still only match one single character (and I don't see a way around that).

Resources