can't get specific query-replace-regexp in emacs to work - regex

I have a block of code as such, and I am trying to modify it with query-replace-regexp in emacs.
fz.D(1,:) = Dcen;
fz.vol(1,:) = (4/3)*pi*((fz.D(1,:)/2).^3);
fz.POC(1,:) = Ac*fz.vol(1,:).^bc;
fz.w(1,:) = cw*fz.D(1,:).^eta;
% size - bin edges
fzl.D(1,:) = Dlim;
I want it to look as so:
fz.D(ind,:) = fz.D(1,:);
fz.vol(ind,:) = fz.vol(1,:);
fz.POC(ind,:) = fz.POC(ind,:);
and so fourth.
I tried to enact this change with the following, but it doesn't seem to work
query-replace-regexp
\(*\)(1,:) = *; -> \1(k,:) = \1(1,:);
But that seems to do nothing.
Any suggestions about how I should fix this?

I don't know emacs, but your regular expression needs to use .* for the 'match any length substring' operation:
query-replace-regexp \(.*\)\((1,:)\) = .*; -> \1(ind,:) = \1\2;
(This also makes use of a second \(\) group to avoid repeating the part of the pattern that you want to repeat in the replacement text)
The reason:
In regular expressions, * is a postfix operator that matches "0 or more of the previous item". When found with no previous item, it matches a plain *. Thus, your expression \(*\)(1,:) = *; matched the exact text *(1,:) = followed by 0 or more spaces followed by ;. You want to use .* to "match anything", as this matches 0 or more . items (where . matches any one non-end-of-line character).

Related

RegEx repeating subcapture returns only last match

I have a regexp that tries to find multiple sub captures within matches:
https://regex101.com/r/nk1Q5J/2/
=\s?.*(?:((?i)Fields\("(\w+)"\)\.Value\)*?))
I've had simpler versions with equivalent results but this is the last iteration.
the Trick here is that the first group looks for a sequence that begins with '=' (to identify database field reads in VB.Net)
The single sub capture cases work:
Match 1. [comparison + single parameter read call]
= False And IsNull(Fields("lmpRoundedEndTime").Value)
=> G2: lmpRoundedEndTime
Match 3. [read into string] oRs.Open "select lmpEmployeeID,lmpShiftID,lmpTimecardDate,lmpProjectID from Timecards where lmpTimecardID = " + App.Convert.NumberToSql(Fields("lmlTimecardID").Value),Connection,adOpenStatic,adLockReadOnly,adCmdText
=> G2: lmlTimecardID
Match 4. [assignment] Fields("lmlEmployeeID").Value = oRs.Fields("lmpEmployeeID").Value
Where I am failing is a match with multiple sub-captures. My regexp returns the last (intended) sub capture :
Match 2. [read multiple input parameters] Fields("lmpPayrollHours").Value = App.Ax("TimecardFunctions").CalculateHours(Fields("lmpShiftID").Value,Fields("lmpRoundedStartTime").Value,Fields("lmpRoundedEndTime").Value)
=> G2: lmpRoundedEndTime
'''''''''''' ^ must capture: lmpShiftID , lmpRoundedStartTime , lmpRoundedEndTime
I've read up on lazy quantifiers etc, but can't wrap my head around where this goes wrong.
References:
https://www.regular-expressions.info/refrepeat.html
http://www.rexegg.com/regex-quantifiers.html
Related:
Regular expression: repeating groups only getting last group
What's the difference between "groups" and "captures" in .NET regular expressions?
BTW, I could quantify the sub capture as {1,5} safely for efficiency, but that's not the focus.
EDIT:
By using negative lookahead to exclude the left side of comparisons, this got me much closer (match 2 above now works):
(?:Fields\("(\w+)"\)\.Value)(?!\)?\s{0,2}[=|<])
but in the following block of code, only the first two are captured:
If oRs.EOF = False Then
If CInt(Fields("lmlTimecardType").Value) = 1 Then
If Trim(oRs.Fields("lmeDirectExpenseID").Value) <> "" Then
Fields("lmlExpenseID").Value = oRs.Fields("lmeDirectExpenseID").Value
End If
Else
If Trim(oRs.Fields("lmeIndirectExpenseID").Value) <> "" Then
Fields("lmlExpenseID").Value = oRs.Fields("lmeIndirectExpenseID").Value
End If
End If
If CInt(Fields("lmlTimecardType").Value) = 2 Then
If Trim(oRs.FIelds("lmeDefaultWorkCenterID").Value) <> "" Then
Fields("lmlWorkCenterID").Value = oRs.FIelds("lmeDefaultWorkCenterID").Value
End If
End If
End If
Capture1:
Fields("lmlExpenseID").Value = oRs.Fields("lmeDirectExpenseID").Value
Capture2:
Fields("lmlExpenseID").Value = oRs.Fields("lmeIndirectExpenseID").Value
Capture3 (failed):
Fields("lmlWorkCenterID").Value = oRs.FIelds("lmeDefaultWorkCenterID").Value
Actually, (?:Fields\("(\w+)"\)\.Value)(?!\)?\s{0,2}[=|<]) does work in my Excel sheet, just not in the regex101 test. Probably a slightly different standard used there.
https://regex101.com/r/p6zFqy/1/

Surrounding one group with special characters in using substitute in vim

Given string:
some_function(inputId = "select_something"),
(...)
some_other_function(inputId = "some_other_label")
I would like to arrive at:
some_function(inputId = ns("select_something")),
(...)
some_other_function(inputId = ns("some_other_label"))
The key change here is the element ns( ... ) that surrounds the string available in the "" after the inputId
Regex
So far, I have came up with this regex:
:%substitute/\(inputId\s=\s\)\(\"[a-zA-Z]"\)/\1ns(/2/cgI
However, when deployed, it produces an error:
E488: Trailing characters
A simpler version of that regex works, the syntax:
:%substitute/\(inputId\s=\s\)/\1ns(/cgI
would correctly inser ns( after finding inputId = and create string
some_other_function(inputId = ns("some_other_label")
Challenge
I'm struggling to match the remaining part of the string, ex. "select_something") and return it as:
"select_something")).
You have many problems with your regex.
[a-zA-Z] will only match one letter. Presumably you want to match everything up to the next ", so you'll need a \+ and you'll also need to match underscores too. I would recommend \w\+. Unless more than [a-zA-Z_] might be in the string, in which case I would do .\{-}.
You have a /2 instead of \2. This is why you're getting E488.
I would do this:
:%s/\(inputId = \)\(".\{-}\)"/\1ns(\2)/cgI
Or use the start match atom: (that is, \zs)
:%s/inputId = \zs\".\{-}"/ns(&)/cgI
You can use a negated character class "[^"]*" to match a quoted string:
%s/\(inputId\s*=\s*\)\("[^"]*"\)/\1ns(\2)/g

What is a Regex equivalent of the 'Trim' function used in languages such as VB and Java..?

I'm using Regex in a Microsoft Access 2007 database with a VBA project reference to Microsoft VBScript Regular Expressions 5.5.
All is well...mostly. I would like to know a Regular Expression that will act like the 'Trim' function..? (remove leading and trailing spaces)
I have this: ((?:.?)*) which is to "capture everything after the last match". But it always matches extra spaces which I would like to remove.
Below is the relevant code, followed by a screenshot of the debugger. Item 4 in the submatches has " CAN". How do I remove the space with Regex, so I don't have to use the Trim function..?
pattern = "^(\d{1,2})(?:\/)(\d{1,2}(?:\.\d{1,3})?)(OZ)((?:.?)*)"
regex.pattern = pattern
Set matchCollection = regex.Execute(workstring)
If matchCollection.Count > 0 Then
matchSection = "LOOSE CASES"
itemtype = "CASE"
percase = matchCollection(0).SubMatches(0)
perpack = 1
unitsize = matchCollection(0).SubMatches(1)
uom = matchCollection(0).SubMatches(2)
other = VBA.Trim(matchCollection(0).SubMatches(3))
End If
...
Ok, I finally figured it out. To reiterate (and clarify): my original regex ((?:.?)*) is meant to "capture anything left after the last match". But it also captured leading & trailing spaces.
Removing the leading spaces was fairly easy, but every attempt to remove the trailing spaces was foiled by the * in the group. Then I read about \b and dropped one in and now it works.
This is what I have now: (?: ?)((?:.?)*)\b(?: *) which is "match anything left after the last match, except leading or trailing spaces".
And in context, this is the whole of it...
(\d{1,2})/(\d{1,2})PK-(\d{1,2}(?:.\d{1,3})?)(OZ|ML)(?: ?)((?:.?)*)\b(?: *)
Which is meant to match on a string such as this...
2/12PK-11.125OZ CAN RET
...which describes cases of beer in our warehouse. =-)

What is the syntax for the pattern in a VBScript RegExp object?

I'm not too familiar with VB script and am having trouble with the syntax for the pattern property of my regexp object.
I have some data that looks like this:
Front SHD Trip CLEAR OBSTRUCTION BEFORE CONTINUING [Table Position =
0mmFwd] Front SHD Trip CLEAR OBSTRUCTION BEFORE CONTINUING [Table
Position = 563mmFwd]
I want to strip off the [Table Position = x] part from these records so I have created a little function. Although there are no errors, it's not stripping off the end of the string as expected and I'm fairly sure that the issue is my syntax in this line:
objRegExp.Pattern = "[*]"
Here's the whole function:
Function RemoveTablePosition(AlarmText)
'Initialise a new RegExp object
Dim objRegExp, strNewAlarmText
Set objRegExp = New Regexp
'Set the RegExp object's parameters
objRegExp.IgnoreCase = True
objRegExp.Global = True
'Look for [Table Position = xx] at the end of the code text (they always follow the same format)
objRegExp.Pattern = "[*]"
'Replace all [Table Position = xx] with the empty string to effectively remove them
strNewAlarmText = objRegExp.Replace(AlarmText, "")
'Return the new alarm text value
RemoveTablePosition = strNewAlarmText
Set objRegExp = Nothing
End Function
Can someone point me in the right direction? Thanks in advance!
"[*]" is a character class matching a * literal character.
You can use
\[[^\]]*]$
or
\[.*?]$
See the regex demo. If you need to also match optional whitespace(s) before the [...], add \s* at the pattern start.
Explanation
\[ - literal [ symbol
[^\]]* - zero or more symbols other than ] (if there can be no [ and ], replace this one with [^\][]*)
OR
.*? - 0+ any characters other than a newline as few as possible up to the first...
] - a literal ] symbol that is at the...
$ - end of string
The difference between \[[^\]]*]$ and \[.*?]$ is that the former will also match newlines in between [ and ] (if any) and \[.*?]$ won't.
Assuming you also wish to get rid of the space after "CONTINUING", you would want to search for:
" \[.*\]$"
This looks for the space, left bracket, any number of characters, a right bracket and end of string.
If the right bracket is not end of string, for example:
Test String [REMOVE [THIS] AND CONTINUE]
it will keep matching with .* until it finds \]$ ($ being end of string.)
Wiktor's examples are good, but
"\[[^\]]*]$" is broken - I think he meant "\[[^\]]*\]$" - the problem with this is that it will stop at the first right bracket, so the example I gave above would fail to match
His second example, "\[.*?]$", also should probably be "\[.+\]$" assuming you wish to ensure there is something within the brackets, which it appears he was going for.
(? looks for 0 or 1, + looks for 1 or more, * looks for 0 or more)
(More elegant to use "\[.*\]$" as this does not make that assumption. ".*" matches 0 or more of any character. Surrounded by \[ and \], it will find anything in a pair of brackets, and ending with the $ assures it is at end of string.)
Hopefully this helps someone - I noted the date before replying, but saw the broken regex. The way the site uses * and hides single \ marks, it could be Wiktor's examples were fine until he posted them... (More than likely, actually.)

How to select a part of a string OR another with REGEXP in MATLAB

I've been trying to solve this problem in the last few days with no success. I have the following string:
comment = '#disabled, Fc = 200Hz'
What I need to do is: if there's the string 'disabled' it needs to be matched. Otherwise I need to match the number that comes before 'Hz'.
The closest solution I found so far was:
regexpi(comment,'\<#disabled\>|\w*Hz\>','match') ;
It will match the word '#disabled' or anything that comes before 'Hz'. Problem is that when it first finds '#disabled#' it copies also the result '200Hz'.
So I'm getting:
ans = '#disabled' '200Hz'
Summing up, I need to select only the 'disabled' part of a string if there is one, otherwise I need to get the number before 'Hz'.
Can someone give me a hand ?
Suppose your input is:
comment = {'#disabled, Fc = 200Hz';
'Fc = 300Hz'}
The regular expression (match disabled if follows # otherwise match digits if they are followed by Hz):
regexp(comment, '(?<=^#)disabled|\d+(?=Hz)','match','once')
Explaining it:
^# - match # at the beginning of the line
(?<=expr)disabled - match disabled if follows expr
expr1 | expr2 - otherwise match expr2
\d+ - match 1 or more digits, equivalently [0-9]+
expr(?=Hz) - match expr only if followed by 'Hz'
Diagram:
Debuggex Demo