Let's assume I have files in a local Github and I need to replace this code
bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
{
if (!fReadTransactions)
{
*this = pindex->GetBlockHeader();
return true;
}
if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions))
return false;
if (GetHash() != pindex->GetBlockHash())
return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
return true;
}
I'm looking for a way to 'scan' the files and match the initial
bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
and replace the code between the brackets {} entirely.
So the only part I know about the blocks I need to replace are the declarations.
To match everything between ( and ) you can use:
(?<=bool CBlock::ReadFromDisk\().*?(?=\))
Dim ResultString As String
Try
ResultString = Regex.Replace(SubjectString, "(?<=bool CBlock::ReadFromDisk\().*?(?=\))", "replacement_text_here", RegexOptions.Multiline)
Catch ex As ArgumentException
'Syntax error in the regular expression
End Try
To match everything between { and } you can use:
(?<=bool CBlock::ReadFromDisk\(const CBlockIndex\* pindex, bool fReadTransactions\)\s*\{)(?:[^{}]|(?<open>{)|(?<-open>}))+(?(open)(?!))(?=\})
Dim ResultString As String
Try
ResultString = Regex.Replace(SubjectString, "(?<=bool CBlock::ReadFromDisk\(const CBlockIndex\* pindex, bool fReadTransactions\)\s*\{)(?:[^{}]|(?<open>{)|(?<-open>}))+(?(open)(?!))(?=\})", "replacement_text_here")
Catch ex As ArgumentException
'Syntax error in the regular expression
End Try
Related
public list[str] deleteBlockComments(list[str] fileLines)
{
bool blockComment = false;
list[str] sourceFile = [];
for(fileLine <- fileLines)
{
fileLine = trim(fileLine);
println(fileLine);
if (/^[\t]*[\/*].*$/ := fileLine)
{
blockComment = true;
}
if (/^[\t]*[*\/].*$/ := fileLine)
{
blockComment = false;
}
println(blockComment);
if(!blockComment)
{
sourceFile = sourceFile + fileLine;
}
}
return sourceFile;
}
For some reason, I am not able to detect /* at the beginning of a string. If I execute this on the command line, it seems to work fine.
Can someone tell me what I am doing wrong? In the picture below you can see the string to be compared above the comparison result (false).
[\/*] is a character set that matches forward slash or star, not both one after the other. Simply remove the square brackets and your pattern should start behaving as you expect.
While we're at it, let's also get rid of the superfluous square brackets around \t
^\t*\/*.*$
I am making a simple dialogue system, and would like to "dynamise" some of the sentences.
For exemple, I have a Sentence
Hey Adventurer {{PlayerName}} !
Welcome in the world !
Now In code I am trying to replace that by the real value of the string in my game. I am doing something like this. But it doesn't work. I do have a string PlayerName in my component where the function is situated
Regex regex = new Regex("(?<={{)(.*?)(?=}})");
MatchCollection matches = regex.Matches(sentence);
for(int i = 0; i < matches.Count; i++)
{
Debug.Log(matches[i]);
sentence.Replace("{{"+matches[i]+"}}", this.GetType().GetField(matches[i].ToString()).GetValue(this) as string);
}
return sentence;
But this return me an error, even tho the match is correct.
Any idea of a way to do fix, or do it better?
Here's how I would solve this.
Create a dictionary with keys as the values you wish to replace and values as what you will be replacing them to.
Dictionary<string, string> valuesToReplace;
valuesToReplace = new Dictionary<string, string>();
valuesToReplace.Add("[playerName]", "Max");
valuesToReplace.Add("[day]", "Thursday");
Then check the text for the values in your dictionary.
If you make sure all of your keys start with "[" and end with "]" this will be quick and easy.
List<string> replacements = new List<string>();
//We will save all of the replacements we are about to perform here.
//This is done so we won't be modifying the original string while working on it, which will create problems.
//We will save them in the following format: originalText}newText
for(int i = 0; i < text.Length; i++) //Let's loop through the entire text
{
int startOfVar = 9999;
if(text[i] == '[') //We have found the beginning of a variable
{
startOfVar = i;
}
if(text[i] == ']') //We have found the ending of a variable
{
string replacement = text.Substring(startOfVar, i - startOfVar); //We have found the section we wish to replace
if (valuesToReplace.ContainsKey(replacement))
replacements.Add(replacement + "}" + valuesToReplace[replacement]); //Add the replacement we are about to perform to our dictionary
}
}
//Now let's perform the replacements:
foreach(string replacement in replacements)
{
text = text.Replace(replacement.Split('}')[0], replacement.Split('}')[1]); //We split our line. Remember the old value was on the left of the } and the new value was on the right
}
This will also work much faster, since it allows you to add as many variables as you wish without making the code slower.
Using Regex.Replace method, and a MatchEvaluator delegate (untested):
Dictionary<string, string> Replacements = new Dictionary<string, string>();
Regex DialogVariableRegex = new Regex("(?<={{)(.*?)(?=}})");
string Replace(string sentence) {
DialogVariableRegex.Replace(sentence, EvaluateMatch);
return sentence;
}
string EvaluateMatch(Match match) {
var matchedKey = match.Value;
if (Replacements.ContainsKey(matchedKey))
return Replacements[matchedKey];
else
return ">>MISSING KEY<<";
}
This is kind of old now, but I figured I'd update the accepted code above. It won't work since the start index is reset every time the loop iterates, so setting startOfVar = i gets completely reset by the time it hits the closing character. Plus there are problems if there's an open bracket '[' and no closing one. You can also no longer use those brackets in your text.
There's also setting the splitter to a single character. It tests fine, but if I set my player name to "Rob}ert", that will cause problems when it performs the replacements.
Here is my updated take on the code which I've tested works in Unity:
public string EvaluateVariables(string str)
{
Dictionary<string, string> varDict = GetVariableDictionary();
List<string> varReplacements = new List<string>();
string matchGuid = Guid.NewGuid().ToString();
bool matched = false;
int start = int.MaxValue;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '{')
{
if (str[i + 1] == '$')
{
start = i;
matched = true;
}
}
else if (str[i] == '}' && matched)
{
string replacement = str.Substring(start, (i - start) + 1);
if (varDict.ContainsKey(replacement))
{
varReplacements.Add(replacement + matchGuid + varDict[replacement]);
}
start = int.MaxValue;
matched = false;
}
}
foreach (string replacement in varReplacements)
{
str = str.Replace(replacement.Split(new string[] { matchGuid }, StringSplitOptions.None)[0], replacement.Split(new string[] { matchGuid }, StringSplitOptions.None)[1]);
}
return str;
}
private Dictionary<string, string> GetVariableDictionary()
{
Dictionary<string, string> varDict = new Dictionary<string, string>();
varDict.Add("{$playerName}", playerName);
varDict.Add("{$npcName}", npcName);
return varDict;
}
I am using this function to perform regex replace on std::string:
String regexReplace(String s,String search,String replace,String modifier,int user){
bool case_sensitive=true,global=false;
String replaced_string=s;
if(modifier=="gi" || modifier=="ig"){global=true;case_sensitive=false;}
else if(modifier=="i"){case_sensitive=false;}
else if(modifier=="g"){global=true;}
try {
std::regex re (search);
if(user==1){re=createRegex(search,case_sensitive);}
else if(!case_sensitive){re= Regex (search, REGEX_DEFAULT | ICASE);}
if(global){
replaced_string=std::regex_replace (s,re,replace,std::regex_constants::format_default);
}
else{
replaced_string=std::regex_replace (s,re,replace,NON_RECURSIVE_REGEX_REPLACE);
}
}
catch (std::regex_error& e) {
printErrorLog("Invalid replace string regex: "+search);
Exit(1);
}
return replaced_string;
}
typedefs and #defines used:
typedef std::regex Regex;
typedef std::string String;
#define REGEX_DEFAULT std::regex::ECMAScript
#define ICASE std::regex::icase
#define NON_RECURSIVE_REGEX_REPLACE std::regex_constants::format_first_only
But this function consumes approximately 0.3 seconds on 14x4 consecutive executions:
res=regexReplace(res,"([^\\.]*\\.\\d+?)0+$","$1","i",0);
res=regexReplace(res,"([^\\.]*\\.\\d+?)0+(e.*)$","$1$2","i",0);
res=regexReplace(res,"([^\\.]*)\\.0*$","$1","i",0);
res=regexReplace(res,"([^\\.]*)\\.0*(e.*)$","$1$2","i",0);
Can I make it more efficient to lessen the execution time?
Note:
The createRegex() function is not being called (user=0 by default).
Hi guys im trying to build a module for nginx and need to match a substring here is what im using to try and match
int match_chan(ngx_http_request_t *r, ngx_pool_t *temp_pool, ngx_str_t *body, ngx_str_t *channel) {
u_char errstr[NGX_MAX_CONF_ERRSTR];
ngx_regex_compile_t *rc;
int captures[2];
if ((rc = ngx_pcalloc(temp_pool, sizeof(ngx_regex_compile_t))) == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unable to allocate memory to compile agent patterns");
return 0;
}
//ngx_memzero(rc, sizeof(ngx_regex_compile_t));
ngx_str_t pat = ngx_string("test(:|%3[Aa])([a-zA-Z0-9]+)");
rc->pattern = pat;
rc->pool = temp_pool;
rc->err.len = NGX_MAX_CONF_ERRSTR;
rc->err.data = errstr;
if (ngx_regex_compile(rc) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unable to compile regex pattern %V", rc->pattern);
return 0;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V, %V", &pat, body);
if (ngx_regex_exec(rc->regex, body, captures, 2) >= 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "It Matched");
//ngx_memcpy(channel->data, body->data + captures[0], body->len);
return 1;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "It did not match");
return 0;
}
ngx_str_t *channel = NULL;
if(match_chan(r, temp_pool, aux, channel)) {
//ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " match: %c", match);
}
and the message that is passed looks like this
2014/07/04 13:28:49 [error] 10695#0: *38 test:([a-z0-9]+), MSG%0Atest%3Ahello%0A%0A%0Awins%00
2014/07/04 13:28:49 [error] 10695#0: *38 It did not match
taken from nginx log
ive tested the regex in a pure C app and that worked fine i thought nginx was similar but i guess it has its differences
ive looked all over google and ive tried looking at nginx modules with still no luck please help me :)
Thanks
Dave
The problem is that the string you are trying to match is URL-encoded, and due to this it doesn't match the pattern provided. There are two options:
Construct a regular expression so it will match encoded string as well ("test(:|%3[Aa])([a-zA-Z0-9]+)" will match both unescaped and escaped forms);
Unescape the string you are matching. In nginx, this is done with the ngx_unescape_uri() function.
http://play.golang.org/p/GM0SWo0qGs
This is my code and playground.
func insert_comma(input_num int) string {
temp_str := strconv.Itoa(input_num)
var validID = regexp.MustCompile(`\B(?=(\d{3})+$)`)
return validID.ReplaceAllString(temp_str, ",")
}
func main() {
fmt.Println(insert_comma(1000000000))
}
Basically, my desired input is 1,000,000,000.
And the regular expression works in Javascript but I do not know how to make this Perl regex work in Go. I would greatly appreciate it. Thanks,
Since lookahead assertion seems to be not supported, I'm providing you a different algorithm with no regexp:
Perl code:
sub insert_comma {
my $x=shift;
my $l=length($x);
for (my $i=$l%3==0?3:$l%3;$i<$l;$i+=3) {
substr($x,$i++,0)=',';
}
return $x;
}
print insert_comma(1000000000);
Go code: Disclaimer: I have zero experience with Go, so bear with me if I have errors and feel free to edit my post!
func insert_comma(input_num int) string {
temp_str := strconv.Itoa(input_num)
var result []string
i := len(temp_str)%3;
if i == 0 { i = 3 }
for index,element := range strings.Split(temp_str, "") {
if i == index {
result = append(result, ",");
i += 3;
}
result = append(result, element)
}
return strings.Join(result, "")
}
func main() {
fmt.Println(insert_comma(1000000000))
}
http://play.golang.org/p/7pvo7-3G-s