Regex as associative array key? - regex

I'm working on a very performance dependent portion of my code in D. For this, I want to have an associative array mapping my data to a Regex so that I can use it later.
When I try to do this, it gives me the error, index is not a type or expression. How can I use this regex as my array key?
Edit: For code, here's what I'm trying to define in my class:
View[Regex] m_routes;
I want that so that I can add the routes like below:
void add(string route, View view)
{
auto regex = regex(route.key, [ 'g', 'i' ]);
if (regex in m_routes)
throw new Exception(format(`Route with path, "%s", is already assigned!`, route));
m_routes[regex] = view;
}
This would then allow me to check the regex against a route, without having to rebuild each one, shown in this method:
View check(string resource)
{
foreach (route; m_routes.byKeyValue())
{
auto match = matchAll(resource, route.key);
// If this regex is a match
// return the view
if (!match.empty)
{
return route.value;
}
}
return null;
}
Any help would be appreciated, thank you!

It seems std.regex.Regex is an alias that takes a type parameter:
(from std.regex.package, line 289 in release 2.071.0)
public alias Regex(Char) = std.regex.internal.ir.Regex!(Char);
In other words, you'll need to specify the char type for the regex. For string, that'd be char:
View[Regex!char] m_routes;

Related

Angular/Typescript RegExp enum

Looking to create an enum for some regex to store in my application to allow for code reuse.
Eg:
export enum Regex {
ONE_DANK_REGEX = /^[dank]+$/g,
FIVE_OUT_OF_SEVEN = /^[meme]{5,7}$/g
}
But:
By not using string literals, I get the TS90010 error: Type RegExpis not assignable to type Regex.
By using string literals, I can't use these in a pattern attribute on my inputs
Eg.
<input ngModel="..." pattern="{{FIVE_OUT_OF_SEVEN}}" .../>
Is this the right way of going about doing this?
You cannot assign a RegExp to an enum, an enum can either be numeric or string-based.
So when it comes to storing the RegExp you have two options:
Option A - store the RegExp as string in an enum
enum RegExpEnum {
ONE_DANK_REGEX = "^[dank]+$",
FIVE_OUT_OF_SEVEN = "^[meme]{5,7}$"
}
Option B - store the RegExp in a class/variable
class RegexClass {
public static readonly ONE_DANK_REGEX = /^[dank]+$/g;
public static readonly FIVE_OUT_OF_SEVEN = /^[meme]{5,7}$/g;
}
In both ways you need to get a reference to the containing enum or class in your component. Which can be achieved by assigning it to a local variable.
#Component({ ... })
public class MyComponent {
availableRegex = RegExpEnum; // or RegexClass
}
Then you can access it in the html part of your component.
<input [(ngModel)]="name" [pattern]="availableRegex.ONE_DANK_REGEX"/>
DEMO
Enum will support only strings and Number.
If you wanted to store regular expressions, you need to use static class
export class RegularExpression
{
public static ALPHA_CHARACTERS: RegExp = /([^A-Za-z])+/g;
}
Usage
'Your_* Name'.replace(RegularExpression.ALPHA_CHARACTERS, '');
Prefer the option A mentioned on the currently accepted answer and use it as below the code:
export enum Regex {
ONE_DANK_REGEX = "^[dank]+$",
FIVE_OUT_OF_SEVEN = "^[meme]{5,7}$",
}
public readonly regOne = new RegExp(Regex.ONE_DANK_REGEX, "g");
This gives some flexibility when create the regular expression object.

Implementing Pattern with RegExp in Dart

I wanted to have a Pattern where I could easily get the base path of the pattern, for use with routing, like this:
var route = new Pattern('/user');
print(route.path)
would give '/user', but the pattern would match r'/user/.*'.
I pictured this would suffice:
class Path extends RegExp {
String _path;
Path(this._path): super(path.join(_path, '.*'));
}
However, RegExp is abstract, so it cannot work. But RegExp is still instantiable because it's constructor is declared with factory. Therefore, I find the only / best solution is to keep a RegExp object as a member:
class Path implements Pattern {
String _path;
RegExp _r;
Path(this._path) {
_r = new RegExp(join(_path, '.*'));
}
Match matchAsPrefix(String string, [int start=0]) {
return _r.matchAsPrefix(string, start);
}
Iterable<Match> allMatches(String str) {
return _r.allMatches(str);
}
}
But the definition of RegExp lists only allMatches, as specified by Pattern. But doesn't all of Patterns method need to be implemented if RegExp is to support Pattern?
I wanted to look at the implementation of RegExp's constructor, but it's defined as external, and I can't find the correct file.
So properly formulate my question, is there any way for me to do what I originally intended, to inherit from a non-abstract class implementing Pattern?
I would recommend that you look at the Uri class or Path package, and see if it can't help you with what you want (and if it can't, file a feature request). Working with paths or URIs as strings is likely to be fragile.
Anyway, if I understand you correctly, you want the input x to be match "$x/" and everything after that. That sounds fairly simple - since it matches to the end of the string, there can only ever be one match per string.
You can write your own Pattern implementation:
class MyPattern implements Pattern {
final String _pattern;
MyPattern(String prefix) : _pattern = "$prefix/";
Iterable<Match> allMatches(String input) {
int index = input.indexOf(_pattern);
if (index < 0) return null;
return [new _MyMatch(input, this, index)];
}
Match matchAsPrefix(String input, [int start = 0]) {
if (input.startsWith(_pattern, start)) {
return new _MyMatch(input, this, start);
}
return null;
}
}
class _MyMatch implements Match {
final String input;
final Pattern pattern;
final int start;
_MyMatch(this.input, this.pattern, this.start);
int get end => input.length;
int get groupCount => 0;
List<String> groups(Iterable<int> indices) {
var result = <String>[];
for (int i in indices) result.add(group(i));
return result;
}
String group(int index) {
if (index == 0) return input.substring(start);
throw new RangeError.value(index);
}
String operator[](int index) => group(index);
}
I think it is fine how you did it (RegExp as member).
The abstract class with the factory constructor is a construct to prevent deriving from RegExp.
The external keyword is a trick to bind to a concrete implementation from somewhere else later (VM or JS, see https://www.dartlang.org/docs/spec/latest/dart-language-specification.html#h.lkkt75qhbiwh).
This is the reason why the abstract class can be instantiated and why RegExp doesn't have to implement all methods in the regexp.dart file.

How to generate Nagios hostgroup list from hosts by using Notepad++/RegEx or other

I'm using Notepad++ and I would like to ask for help to achieve the following.
I have some(several 1000 lines) Nagios/Icinga config that looks like this:
define host {
use generic-host
host_name FakeNameA-748-SomeNameA
alias FakeNameA-748-SomeNameA
address 10.1.1.97
}
define host {
use generic-host
host_name H548-AP02
alias H548-AP02
address 172.19.115.190
}
define host {
use generic-host
host_name FakeNameB-302-SomeNameB
alias FakeNameB-302-SomeNameB
address 192.168.149.1
}
define host {
use generic-host
host_name FakeNameC-902-Acronym
alias FakeNameC-902-Acronym
address 192.168.48.1
}
define host {
use generic-host
host_name H902-AP01
alias H902-AP01
address 192.168.48.190
}
I need to create some hostgroups that contain all the host names, but in two groups.
Like this:
define hostgroup {
hostgroup_name GroupA
alias GroupA
members FakeNameA-748-SomeNameA,FakeNameB-302-SomeNameB,FakeNameC-902-Acronym
}
define hostgroup {
hostgroup_name GroupB
alias GroupB
members H548-AP02,H902-AP01
}
As you can see, if the "host_name" contains "AP" it should go into GroupB and everything else into GroupA(note that they should be comma separated).
Does anyone have some idea of how i could automate this?
Thank you for your time :)
If your hostnames match the schema in your example you can do this dynamically with regular expression matching that comes with Nagios:
nagios.cfg:
use_regexp_matching=1
.
define hostgroup {
hostgroup_name GroupA
members ^[^-]+-[0-9]+-[^-]$
}
define hostgroup {
hostgroup_name GroupB
members ^[^-]+-AP[0-9]+$
}
Unfortunately the regular expression engine used does not support lookbehind/lookahead, otherwise this could be achieved more easily and reliably. As it is, you have to find expressions that match one group but not the other for both groups in question.
On a side note, why do you bother setting aliases that are the same as the hostnames?
I solved this(with some help ;) ).
I used the program called LINQPad with the following code:
void Main()
{
List<string> lines= GetLines();
List<string> hostNames = new List<string>();
string members = "10.0.1.191,10.0.1.193,10.0.107.190";
foreach(string member in members.Split(','))
{
var index = lines.FindIndex((s) => s.Contains(member));
string aliasLine = lines[index + 1];
int count = aliasLine.IndexOf("\t\t");
string hostName = aliasLine.Remove(0, count + 2);
hostNames.Add(hostName);
}
string.Join(",",hostNames).Dump();
}
List<string> GetLines()
{
List<string> lines = new List<string>();
using (var sr = new StreamReader("c:\\temp\\Nagios_Host_List.txt")) {
while (!sr.EndOfStream)
{
lines.Add( sr.ReadLine());
}
}
return lines;
}
Because I already had a members list with all the IP addresses in a single comma seperated line, I just pasted this besides the "string members = ..." and the txt file contained all the host entries.
The result was a single line with comma separated host names. Just what i needed.
It solved my specific issue at the moment. But when we will be upgrading from Nagios to Icinga in the future. I will be taking into account what #Adrian Frühwirth posted.
This way we could automate it more.
Hopefully someone can use this information to there advantage :)
Happy day.

What type should my variable be declared as?

I am new to C# / OOP and am working on converting an existing application into .net 4.0 framework.
My code is as follows:
Class abc
private IList<string[]> GetReportBatchList()
{
List<string[]> rowList = new List<string[]>();
SqlParameter[] prm = { new SqlParameter("#rpt_doc_type_id", SqlDbType.Int, 9) };
prm[0].Value = 101;
try
{
.....
.....
.....
}
return rowList;
}
class xyz
using abc;
Private Function GenerateReport()
Try
{
Dim rptBatchList As ??????
rptBatchList = GetReportBatchList()
While rptBatchList.Read()
......
......
......
}
catch
{
......
}
What type should rptBatchList be declared as?
Since the return value of GetReportBatchList() has IList of string as its type, it makes sense that rptBatchList should be the same type.
Your second example is VB, but you say you are using C#, so...
For C# it would be IList<string[]>.
My VB is a little rusty, but I think it would be IList(Of String()).
Hmmm... is this a question about correct return types, or a question about translating C# into VB.Net?
According to the function definition you have, rptBatchList will be of type IList<string[]> - obviously declared in the correct syntax for VB.Net.
Further to that, because it is a list of string arrays, it doesn't have a Read() function, so maybe you were looking for something that derives from DbDataReader instead (like a SqlDataReader)? If you do intend to stick with the current definition then you can use either a foreach or a for loop to iterate over the list elements, or you can use Linq extensions and use something like this:
rptBatchList.ForEach(z => { z.ForEach(x => doSomethingWithThisResultString(x)); } );
although that can get messy fast - you probably want to just stick with a couple of nested foreach loops.

ExpressionEngine templates: pass a plugin/module's output as parameter to another plugin/module

Here's basically what I want to accomplish:
{exp:plugin1:method arg="{exp:plugin2:method}"}
I’ve tried a number of different approaches.
Approach 1:
{exp:plugin1:method arg="{exp:plugin2:method}"}
Result: Plugin1->method’s arg parameter value is the string, {exp:plugin2:method}, and it’s never parsed.
Approach 2:
My understanding of the parsing order suggests that this might have different results, but apparently it does not.
{preload_replace:replaced="{exp:plugin2:method}"}
{exp:plugin1:method arg="{replaced}"}
Result: The arg parameter has the same value as approach 1.
Approach 3:
First I define a snippet (snip), whose content is:
{exp:plugin2:method}
Then in the template:
{exp:plugin1:method arg="{snip}"}
Result: Same as approaches 1 and 2.
Approach 4:
Noting that plugins are processed in the order they appear, I have even tested simply placing an instance of {exp:plugin2:method} before the {exp:plugin1:method} call. My thinking is that I could wrap this first call in a regex replacement plugin in order to suppress output, but that it would trigger Plugin2’s parsing first.
{exp:plugin2:method}
{exp:plugin1:method arg="{exp:plugin2:method}"}
Result: Plugin1->method’s arg parameter value is the temporary hash placeholder for Plugin2->method’s output (MD5 I believe) that the Template class reserves until later.
Interesting approach. However, this can be achieved more simply like this:
{exp:plugin1:method arg="{exp:plugin2:method}" parse="inward"}
I have a workaround, but I'll wait a while to see if a better solution comes up before I accept my own answer. The workaround is to wrap plugin1 with plugin2 and replace template tags referring to its methods within the tagdata. Note that this requires a parse="inward" parameter on the plugin2 call.
In the template:
{exp:plugin2 parse="inward"}
{exp:plugin1:method arg="{someplugin2method}"}
{/exp:plugin2}
In the plugin class:
static $public_methods;
function __construct() {
// Actual construction code omitted...
if(($tagdata = $this->EE->TMPL->tagdata) !== false && trim($tagdata) !== '') {
if(!isset(self::$public_methods)) {
self::$public_methods = array();
$methods = get_class_methods($this);
foreach($methods as $method) {
if($method == get_class($this) || $method == '__construct') {
continue;
}
$reflection = new ReflectionMethod(get_class($this), $method);
if($reflection->isPublic()) {
self::$public_methods[] = $method;
}
}
self::$public_methods = implode('|', self::$public_methods);
}
$tagdata = preg_replace_callback('/\{(' . self::$public_methods . ')\}/',
array($this, 'tagdata_callback'), $tagdata);
$this->return_data = $tagdata;
}
}
private function tagdata_callback($matches) {
$method = $matches[1];
return $this->$method();
}
Caveats:
This can make for messier templates.
Maintaining a list of public methods apparently requires Reflection which is not available in PHP 4. You can, of course, maintain a list of expected methods manually.