Qt- checking regular expression width - c++

I'm trying to replace regular expression with different expression which depend on width of line and width of box.
Here is my code:
//mangledText is my text that I've searching on it
//rx is regular expression
QRegExp rx("<lms([^<]*)/>");
while ((pos = rx.indexIn(mangledText)) != -1){
for (int j = 0; j < tempLayout->lineCount(); j++){
QTextLine tl = tempLayout->lineAt(j);
//here is width of each line
int naturalTextWidth = tl.naturalTextWidth();
//rect width is maximum width of box
if (naturalTextWidth < rectWidth)
mangledText.replace(pos, rx.matchedLength(), "replace Text");
else
mangledText.replace(pos, rx.matchedLength(), "\n replace Text");
}
}
mangledText.replace('\n', QChar::LineSeparator);
I want to replace regular expression with "\n replace Text" if text on that line is out of box. otherwise I replace it with "replace Text" . Problem is it will always shift it to next line. because rectWidth is smaller that naturalTextWidth. but I want to check an each regular expression to replace.
UPDATED:
For example :
111111111111111111111111111<lms8><lms3><lms2>
is showing :
111111111111111111111111111
<lms8>
<lms3>
<lms2>
and I want this:
111111111111111111111111111
<lms8><lms3><lms2>
Any suggestion?

Try this.
(.[^<]*)(<lms.*>)
Replace with following syntax.
$1\n$2
The result would be
111111111111111111111111111
<lms8><lms3><lms2>

Related

wpf richtextbox selection with regex

i want to color the matched text of a file.
first,i load the file text into FileItem.Content ,then use regex to get the matches,and next put the Content into a richtextbox and use the matches to set the caret position and color the text .
and the code to fill richtextbox
RtbCodes.Document.Blocks.Clear();
RtbCodes.Document.Blocks.Add(new Paragraph(new Run(item.Content)));
foreach (Match m in item.Matches)
{
TextPointer start1 = RtbCodes.Document.ContentStart.GetPositionAtOffset(m.Index, LogicalDirection.Forward);
TextPointer end = RtbCodes.Document.ContentStart.GetPositionAtOffset(m.Index + m.Length, LogicalDirection.Backward);
if (start1 != null && end != null)
{
RtbCodes.Selection.Select(start1, end);
RtbCodes.Selection.ApplyPropertyValue(Run.BackgroundProperty, "red");
}
}
my problem is the caret selection is not correct at all. see the picture bellow.
my regex expression is [\$#]{[.a-zA-Z\d]+} ,so it will get #{blacklist.model1} , but it not.
so ,what's wrong with richtextbox ?
You are counting in the invisible "ElementStart" symbols at the beginning of the document, that's why the offset of the selection is incorrect.
To get the correct position, you can count from the beginning of the Run element.
var newRun = new Run(item.Content);
RtbCodes.Document.Blocks.Add(new Paragraph(newRun));
TextPointer start1 = newRun.ContentStart.GetPositionAtOffset(m.Index, LogicalDirection.Forward);
TextPointer end = newRun.ContentStart.GetPositionAtOffset(m.Index + m.Length, LogicalDirection.Backward);

CRichEditCtrl - RegEx

How do use RegEx search in RichEditCtrl.
The problem I have is to highlight the first instance of text matching a list of regular expressions (the regular expressions can be duplicate, in that case, first regex matches the first instance and the second the second, and so on).
Since FindText does not support regex, I am trying to get all text starting with index 0, match first regular expression, find the match, and then issue the FindText on the matched text, highlight the matched indices, repeat the search from the matched end index and the next regular expression.
int iSearchStart = 0;
for (auto &regexString : regexStrings) {
CString text_cstr;
int txtLength = myRichEdit.GetTextLength();
// I am getting an exception on second regex on the following statement
myRichEdit.GetTextRange(iSearchStart, txtLength-iSearchStart, text_cstr);
string text = text_cstr;
std::smatch match;
std::regex regexObj(regexString);
//look for the first match in the text
string matchedString;
if (std::regex_search(text, match, regexObj)) {
matchedString = match.str();
FINDTEXTEX ft;
ft.chrg.cpMin = iSearchStart;
ft.chrg.cpMax = -1;
//ft.lpstrText = _T(tw.c_str());
ft.lpstrText = _T(matchedString.c_str());
int iFound = myRichEdit.FindText(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD, &ft);
if (iFound != -1) {
myRichEdit.SetSel(ft.chrgText);
CHARFORMAT2 cf;
::memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_BACKCOLOR;
cf.crBackColor = RGB(255, 160, 160); // pale red
myRichEdit.SetSelectionCharFormat(cf);
iSearchStart = ft.chrgText.cpMax + 1;
}
}
}
I found the problem, I though the second param to GetTextRange is length of the text, but it is actually index of the end.
So if I change
myRichEdit.GetTextRange(iSearchStart, txtLength-iSearchStart, text_cstr);
to
myRichEdit.GetTextRange(iSearchStart, txtLength, text_cstr);
it works!!
I am keeping the code for community to see one way to use regex with CRichEditCtrl.

finding a character in a pattern in regular expression

I am trying to find all occurances of equals within quotes in a string
If my input string is:
anything='', bob2='age=24, sex=M', dilan=24, noble1='yellow'
I wish to find my characters as follows
anything='', bob2='age=24, sex=M', dilan=24, nobel1=24
^ ^
Followed by replacing it as
anything='', bob2='age~24, sex~M', dilan=24, nobel1=24
^ ^
I tried the following to find all the occurances
'[^',].+?'
But that didnt work.
It's quite difficult to implement your requirement just by regex.
I'd like to iterate the String char by char to implement it.
Please check the code below. I have put the comment inside it. I'm using Java but you can utilize the algorithm inside it.
public class Main {
public static void main(String args[]){
String input = "param1='', param2='age<b>=</b>24, sex<b>=</b>M', param3=24, param4='yellow'";
char[] arr = input.toCharArray();
boolean close = true;
/**
* Iterate the char array
*/
for(int i = 0;i < arr.length;i++){
if(arr[i] == '\''){
/**
* Ignore the escaped ' char in ''
*/
if(i > 0 && arr[i - 1] == '\\'){
break;
}
/**
* Use close to check whether equal sign is inside the ''
*/
if(close){
close = false;
}else{
close = true;
}
}else if(arr[i] == '='){
if(!close){
arr[i] = '~';
}
}
System.out.print(arr[i]);
}
}
}
Try this:
(?<!param[\d+])=
And replace by this:
~
Breakdown:
it will look for any '=' and will see if that precedes by param[\d+] or not..
if not preceded by param\d+ then it will capture the = sign.
That = will be replaced by ~
Explanation
You can use the groups to do that with regex.
Try this code:
(?<=age)(\=)(\S+\s\w+)(\=)
Then, substitute the 1st and 3rd group with ~, and keep the 2nd group intact: ~$2~
Demo: https://regex101.com/r/qxR9ty/1
Update
You can first use Negative Lookbehind as suggested by #Maverick_Mrt, and then cancel whatever category you want to exclude by adding | e.g. cat1|cat2
(?<!app|policy_name|dvc_host|sender|sal)\=
Demo: https://regex101.com/r/qxR9ty/

Regular expression for highlighting words in quotes int qt5

I use QHighlighter class, and used regExp to highlight words in quotes:
void Highlighter::highlightBlock(const QString &text)
{
QRegExp expr("\"(.*?)\"");
int index = expr.indexIn(text);
while(index >=0)
{
int length = expr.matchedLength();
setFormat(index, length, Qt::red);
index = expr.indexIn(text, index+length);
}
}
It doesn't work. Work this:
"\".*\""
But it highlights unnecessary. What regular expression is correct?
Just higlight everything between quotes
QRegExp("\"([^\"]*)\"");
highlight single words (run in loop with offset to match words)
QRegExp("\"(\\w)*\"");
How to match words in quotes:
('|")[^\1]*?\1
Example:
http://regex101.com/r/iF5aA1

My last regular expression won't work but i cannot figure out the reason why

I have two vectors, one which holds my regular expressions and one which holds the string in which will be checked against the regular expression, most of them work fine except for this one (shown below) the string is a correct string and matches the regular expression but it outputs incorrect instead of correct.
INPUT STRING
.C/IATA
CODE IS BELOW
std::string errorMessages [6][6] = {
{
"Correct Corparate Name\n",
},
{
"Incorrect Format for Corporate Name\n",
}
};
std::vector<std::string> el;
split(el,message,boost::is_any_of("\n"));
std::string a = ("");
for(int i = 0; i < el.size(); i++)
{
if(el[i].substr(0,3) == ".C/")
{
DCS_LOG_DEBUG("--------------- Validating .C/ ---------------");
output.push_back("\n--------------- Validating .C/ ---------------\n");
str = el[i].substr(3);
split(st,str,boost::is_any_of("/"));
for (int split_id = 0 ; split_id < splitMask.size() ; split_id++ )
{
boost::regex const string_matcher_id(splitMask[split_id]);
if(boost::regex_match(st[split_id],string_matcher_id))
{
a = errorMessages[0][split_id];
DCS_LOG_DEBUG("" << a )
}
else
{
a = errorMessages[1][split_id];
DCS_LOG_DEBUG("" << a)
}
output.push_back(a);
}
}
else
{
DCS_LOG_DEBUG("Do Nothing");
}
st[split_id] = "IATA"
splitMask[split_id] = "[a-zA-Z]{1,15}" <---
But it still outputs Incorrect format for corporate name
I cannot see why it prints incorrect when it should be correct can someone help me here please ?
Your regex and the surrounding logic is OK.
You need to extend your logging and to print the relevant part of splitMask and st right before the call to boost::regex_match to double check that the values are what you believe they are. Print them surrounded in some punctuation and also print the string length to be sure.
As you probably know, boost::regex_match only finds a match if the whole string is a match; therefore, if there is a non-printable character somewhere, or maybe a trailing space character, that will perfectly explain the result you have seen.