AHK help regarding RegExReplace - regex

I need assistance with RegExReplace in AHK.
I want my script to search text and keep only numbers after $ sign.
Right now I have:
F1::
Clipboard =
SendInput, ^c
ClipWait
Variable := Clipboard
NewVar := RegExReplace(Variable,"[^.0-9]+", "{+}")
send % NewVar
return
For example if text is "unit $400 unit 500 $400" I get 400+500+400+
What I would like to get is "400+400+"
I havent been able to figure out how to exclude numbers that dont have $ and I am not sure RegEx is the best thing to use here.
Any help would be great!

This is the final version, that does what I need. Thank you all for advise!!!
F1::
Clipboard =
SendInput, ^c
ClipWait
Pos := 1
While Pos {
Pos:=RegExMatch( Clipboard, "\$(\d+(?:\.\d+)?)", M, Pos+StrLen(M1) )
Match%A_Index% := M1
M2 := M2 Match%A_Index% "{+}"
}
Send % "=sum(" M2
Send {BS}{BS}){enter}
M2 :=
return

NewVar := RegExReplace(Variable, "^.*?\s\$")
NewVar := RegExReplace(NewVar, "\s.*?\$", "+")

I don't know how to do this with RegExReplace, but I can suggest an example using the RegExMatch function.
Unfortunately, AutoHotkey doesn't support the /g/ flag for the global searching, so you have to use a loop to search all values you need.
#NoEnv
SendMode Input
F1::
Clipboard =
SendInput, ^c
ClipWait
i := 1
while pos := RegExMatch(Clipboard, "\$(\d+)", match, i)
{
i += pos
sendinput % match1 "{+}"
}
; sendinput {backspace} ; uncomment this line if you want the last PLUS character to be removed
return

Related

APEX: blob data in mysql from query and output as CSV

Morning folks, could really use your help on this one.
I have a query from a table I need to send out as a CSV attachment on an email using oracle apex. that's the goal of all of this - happy to explore different options/sql to get the same result (through oracle apex)
Example query: select user, title, dept from user_db where dept = :DEPARTMENT
My query brings back a huge amount of data (intended)
Based on this, my idea was to make this query into a BLOB and save it to a different table (TBL_EMAIL_CONTENT),which I could then use the APEX_MAIL.ADD_ATTACHMENT function to bring into an email.
I took the query and created a CLOB, then used a separate function to change the CLOB to a BLOB
declare
CSV_CONTENT clob;
l_BLOB BLOB;
crlf varchar2(2) := chr(13) || chr(10);
CSVFILENAME varchar2(255);
begin
CSV_CONTENT := 'User,'||'Title,'||'Dept,'||crlf;
for c5 in (select user, title, dept from user_db where dept = :DEPARTMENT)
LOOP
CSV_CONTENT := CSV_CONTENT||c5.CONTENT_csv;
CSVFILENAME := 'Example.csv';
END LOOP;
L_BLOB := clob_to_blob(CSV_CONTENT);
for c6 in (select * from TBL_EMAILCONTENT where EMAIL_ID = 1)
LOOP
Update TBL_EMAILCONTENT
set
filename = CSVFILENAME||'.CSV',
CONTENT2 = csv_content,
CONTENT = L_BLOB;
END LOOP;
END;
The clob_to_blob function is as follows:
create or replace FUNCTION clob_to_blob(src_clob CLOB) RETURN BLOB IS
tgt_blob BLOB;
amount INTEGER := DBMS_LOB.lobmaxsize;
dest_offset INTEGER := 1;
src_offset INTEGER := 1;
blob_csid INTEGER := nls_charset_id('UTF8');
lang_context INTEGER := DBMS_LOB.default_lang_ctx;
warning INTEGER := 0;
begin
if src_clob is null then
return null;
end if;
DBMS_LOB.CreateTemporary(tgt_blob, true);
DBMS_LOB.ConvertToBlob(tgt_blob, src_clob, amount, dest_offset, src_offset, blob_csid, lang_context, warning);
return tgt_blob;
end clob_to_blob;
I would then send this out using :
APEX_MAIL.SEND(
p_to => 'UKSERVERPATCHING#VODAFONE.COM',
p_from => 'ukserverpatching#vodafone.com',
p_bcc => 'ukserverpatching#vodafone.com',
p_body => to_clob(' '),
p_body_html => l_body,
p_subj => l_subj);
for c8 in(
SELECT CONTENT,FILENAME,MIMETYPE
FROM TBL_EMAILCONTENT
where EMAIL_ID = 1)
loop
APEX_MAIL.ADD_ATTACHMENT(
p_mail_id => l_id,
p_attachment => c8.CONTENT,
p_filename => c8.FILENAME,
p_mime_type => c8.MIMETYPE);
end loop;
Unfortunately, this result makes a CSV that isnt readable with garbled characters in it. Other options ive tried online so far seem to run into problems where the query result is too long to be dealt with via a varchar value.
has anyone came across this before or can point me to an article online that looks to do this sort of thing?
Thanks in advance, really appreciated.

Excel data import in specific cell

I would like to list up devices and put their prices next to them.
My goal is to check different sites every week and notice trends.
This is a hobby project, I know there are sites that already do this.
For instance:
Device | URL Site 1 | Site 1 | URL Site 2 | Site 2
Device a | http://... | €40,00 | http://... | €45,00
Device b | http://... | €28,00 | http://... | €30,50
Manually, this is a lot of work (checking every week), so I thought a Macro in Excel would help. The thing is, I would like to put the data in a single cell and excel only recognises tables. Solution: view source code, read price, export price to specific cell.
I think this is all possible within Excel, but I can't quiet figure out how to read the price or other given data and how to put it in one specific cell. Can I specify coordinates in the source code, or is there a more effective way of thinking?
First of all you have to find out how does the website works. For the page you asked I have done the following:
Opened http://www.mediamarkt.de page in Chrome.
Typed BOSCH WTW 85230 in the search box, suggestion list appeared.
Pressed F12 to open developer tools and clicked Network tab.
Each time I was typing, the new request appeared (see yellow areas):
Clicked the request to examine general info:
You can see that it uses GET method and some parameters including url-encoded product name.
Clicked the Response tab to examine the data returning from the server:
You can see it is a regular JSON, full content is as follows:
{"suggestions":[{"attributes":{"energyefficiencyclass":"A++","modelnumber":"2004975","availabilityindicator":"10","customerrating":"0.00000","ImageUrl":"http://pics.redblue.de/artikelid/DE/2004975/CHECK","collection":"shop","id":"MediaDEdece2358813","currentprice":"444.00","availabilitytext":"Lieferung in 11-12 Werktagen"},"hitCount":0,"image":"http://pics.redblue.de/artikelid/DE/2004975/CHECK","name":"BOSCH WTW 85230 Kondensationstrockner mit Warmepumpentechnologie (8 kg, A++)","priority":9775,"searchParams":"/Search.ff?query=BOSCH+WTW+85230+Kondensationstrockner+mit+W%C3%A4rmepumpentechnologie+%288+kg%2C+A+%2B+%2B+%29\u0026channel=mmdede","type":"productName"}]}
Here you can find "currentprice":"444.00" property with the price.
Simplified the request by throwing out some optional parameters, it turned out that the same JSON response can be received by the URL http://www.mediamarkt.de/FACT-Finder/Suggest.ff?channel=mmdede&query=BOSCH+WTW+85230
That data was enough to built some code, assuming that first column intended for products:
Option Explicit
Sub TestMediaMarkt()
Dim oRange As Range
Dim aResult() As String
Dim i As Long
Dim sURL As String
Dim sRespText As String
' set source range with product names from column A
Set oRange = ThisWorkbook.Worksheets(1).Range("A1:A3")
' create one column array the same size
ReDim aResult(1 To oRange.Rows.Count, 1 To 1)
' loop rows one by one, make XHR for each product
For i = 1 To oRange.Rows.Count
' build up URL
sURL = "http://www.mediamarkt.de/FACT-Finder/Suggest.ff?channel=mmdede&query=" & EncodeUriComponent(oRange.Cells(i, 1).Value)
' retrieve HTML content
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", sURL, False
.Send
sRespText = .responseText
End With
' regular expression for price property
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = """currentprice""\:""([\d.]+)""" ' capture digits after 'currentprice' in submatch
With .Execute(sRespText)
If .Count = 0 Then ' no matches, something going wrong
aResult(i, 1) = "N/A"
Else ' store the price to the array from the submatch
aResult(i, 1) = .Item(0).Submatches(0)
End If
End With
End With
Next
' output resultion array to column B
Output Sheets(1).Range("B1"), aResult
End Sub
Function EncodeUriComponent(strText)
Static objHtmlfile As Object
If objHtmlfile Is Nothing Then
Set objHtmlfile = CreateObject("htmlfile")
objHtmlfile.parentWindow.execScript "function encode(s) {return encodeURIComponent(s)}", "jscript"
End If
EncodeUriComponent = objHtmlfile.parentWindow.encode(strText)
End Function
Sub Output(oDstRng As Range, aCells As Variant)
With oDstRng
.Parent.Select
With .Resize( _
UBound(aCells, 1) - LBound(aCells, 1) + 1, _
UBound(aCells, 2) - LBound(aCells, 2) + 1 _
)
.NumberFormat = "#"
.Value = aCells
.Columns.AutoFit
End With
End With
End Sub
Filled worksheet with some product names:
Launched the sub and got the result:
It is just the example how to retrieve a data from the website via XHR and parse a response with RegExp, I hope it helps.

How can I split the xml file using regular expression in Perl

Here
<root>
<SchoolOrInstitution schoolType="highschool">
<SchoolName>BUTLER HIGH SCHOOL</SchoolName>
<Degree degreeType="highschool"/>
</SchoolOrInstitution>
<SchoolOrInstitution schoolType="highschool">
<SchoolName>BUTLER HIGH SCHOOL</SchoolName>
<Degree degreeType="highschool"/>
</SchoolOrInstitution>
<SchoolOrInstitution schoolType="highschool">
<SchoolName>BUTLER HIGH SCHOOL</SchoolName>
<Degree degreeType="highschool"/>
</SchoolOrInstitution>
..............
</root>
I want to split this xml in to mutiple file based on the number of SchoolOrInstitution tag.
Each XML should have 3 such tag.
So if the mail file has 9 SchoolOrInstitution tags, it should create 3 child file.
And root tag will also assign to to all the 3 files.
xml_split is a tool that comes with XML::Twig that seems quite close to what you are looking for. xml_split -g3 -l1 my.xml will get you most of the way, the only difference being that the top level element will have a tag name that's assigned by the tool instead of being the original name.
Using xsh, a wrapper around XML::LibXML:
my $old := open 19741254.xml ;
my $n = 1;
while $old/root/SchoolOrInstitution[1] {
my $new := create root ;
xmv $old/root/SchoolOrInstitution[position() <= 3] into $new/root ;
save :f concat($n, '.xml') $new ;
$n = $n + 1 ;
}

capture 2 texts from the screen and compare them using AutoHotkey

I'm working with AutoHotkey and I need to capture two sentences from my screen and compare them. Anyone knows how to do it?
Thanks a lot!!!
OK, this shows some effort.
When you use mouseClickDrag, you have to be absolutely sure that the text will ALWAYS be at those exact locations, which is very unlikely, think about a menu bar moving the webpage down, or about using F11, doing the opposite, changing the font style/size, just zooming in/out, or making the window smaller, such that the text block becomes smaller in width but longer in length, having another banner add that is smaller or larger, et cetera. If you can use an other method (e.g. Find text and from that position, jump 10 words to the left (^{Left 10}) and then select the next 5 words (+^{Right 5}), would be much more reliable.
#NoEnv
#SingleInstance Force
#installKeybdHook
#Persistent
Return ; Stop here on startup to prevent running the whole script on startup
+Insert:: ; Using the [Shift]+[Insert] Key as the hotkey here.
MouseClickDrag,left, 540, 295, 602, 295 ; HighLight area1
Send, ^c
ClipWait, 2
MyVar1:=ClipBoard ; OR MyVar1 = %ClipBoard%
MouseClickDrag,left, 540, 295, 602, 295 ; HighLight area2
Send, ^c
ClipWait, 2
MyVar2:=ClipBoard ; OR MyVar2 = %ClipBoard%
If (MyVar1 = MyVar2)
{
MsgBox, The values %MyVar1% and %MyVar2% are equal
Send, %MyVar1%
; ClipBoard:=MyVar1 ; OR ClipBoard = %MyVar1% is alternative way (Faster)
; Send, ^v
}
Else
{
MsgBox, The values %MyVar1% and %MyVar2% are NOT equal
Send, %MyVar1% AND %MyVar2%
; ClipBoard = %MyVar1% AND %MyVar2% ; is alternative way (Faster)
; Send, ^v
}
Return
You could add some tests to only execute this when Chrome, FireFox or IE is active, but I have left that out. First chew on this code.

Match regex from right to left?

Is there any way of matching a regex from right to left? What Im looking for is a regex that gets
MODULE WAS INSERTED EVENT
LOST SIGNAL ON E1/T1 LINK OFF
CRC ERROR EVENT
CLK IS DIFF FROM MASTER CLK SRC OF
from this input
CLI MUX trap received: (022) CL-B MCL-2ETH MODULE WAS INSERTED EVENT 07-05-2010 12:08:40
CLI MUX trap received: (090) IO-2 ML-1E1 EX1 LOST SIGNAL ON E1/T1 LINK OFF 04-06-2010 09:58:58
CLI MUX trap received: (094) IO-2 ML-1E1 EX1 CRC ERROR EVENT 04-06-2010 09:58:59
CLI MUX trap received: (009) CLK IS DIFF FROM MASTER CLK SRC OFF 07-05-2010 12:07:32
If i could have done the matching from right to left I could have written something like everything to right of (EVENT|OFF) until the second appearance of more than one space [ ]+
The best I managed today is to get everything from (022) to EVENT with the regex
CLI MUX trap received: \([0-9]+\)[ ]+(.*[ ]+(EVENT|OFF))
But that is not really what I wanted :)
edit: What language its for? Its actually a config string for a filter we have but my guess it is using standard GNU C Regex library.
edit2: I like the answers about cutting by length but Amarghosh was probably more what I was looking for. Do not really know why I did not think about just cutting on length like:
^.{56}(.{39}).*$
Super thanks for the quick answers...
In .NET you could use the RightToLeft option :
Regex RE = new Regex(Pattern, RegexOptions.RightToLeft);
Match theMatch = RE.Match(Source);
With regex, you could simply replace this:
^.{56}|.{19}$
with the empty string.
But really, you only need to cut out the string from "position 56" to "string-length - 19" with a substring function. That's easier and much faster than regex.
Here's an example in JavaScript, other languages work more or less the same:
var lines = [
'CLI MUX trap received: (022) CL-B MCL-2ETH MODULE WAS INSERTED EVENT 07-05-2010 12:08:40',
'CLI MUX trap received: (090) IO-2 ML-1E1 EX1 LOST SIGNAL ON E1/T1 LINK OFF 04-06-2010 09:58:58',
'CLI MUX trap received: (094) IO-2 ML-1E1 EX1 CRC ERROR EVENT 04-06-2010 09:58:59',
'CLI MUX trap received: (009) CLK IS DIFF FROM MASTER CLK SRC OFF 07-05-2010 12:07:32'
];
for (var i=0; i<lines.length; i++) {
alert( lines[i].substring(56, lines[i].length-19) );
}
If tokens are guaranteed to be separated by more than one space and words within the string before EVENT|OFF are guaranteed to be separated by just one space - only then you can look for single-space-separated words followed by spaces followed by EVENT or OFF
var s = "CLI MUX trap received: (022) CL-B MCL-2ETH MODULE WAS INSERTED EVENT 07-05-2010 12:08:40"
+ "\nCLI MUX trap received: (090) IO-2 ML-1E1 EX1 LOST SIGNAL ON E1/T1 LINK OFF 04-06-2010 09:58:58"
+ "\nCLI MUX trap received: (094) IO-2 ML-1E1 EX1 CRC ERROR EVENT 04-06-2010 09:58:59"
+ "\nCLI MUX trap received: (009) CLK IS DIFF FROM MASTER CLK SRC OFF 07-05-2010 12:07:32"
var r = /\([0-9]+\).+?((?:[^ ]+ )* +(?:EVENT|OFF))/g;
var m;
while((m = r.exec(s)) != null)
console.log(m[1]);
Output:
MODULE WAS INSERTED EVENT
LOST SIGNAL ON E1/T1 LINK OFF
CRC ERROR EVENT
CLK IS DIFF FROM MASTER CLK SRC OFF
Regex: /\([0-9]+\).+?((?:[^ ]+ )* +(?:EVENT|OFF))/g
\([0-9]+\) #digits in parentheses followed by
.+? #some characters - minimum required (non-greedy)
( #start capturing
(?:[^ ]+ )* #non-space characters separated by a space
` +` #more spaces (separating string and event/off -
#backticks added for emphasis), followed by
(?:EVENT|OFF) #EVENT or OFF
) #stop capturing
Does the input file fit nicely into fixed width tabular text like this? Because if it does, then the simplest solution is to just take the right substring of each line, from column 56 to column 94.
In Unix, you can use the cut command:
cut -c56-94 yourfile
See also
Wikipedia/Cut (Unix)
In Java, you can write something like this:
String[] lines = {
"CLI MUX trap received: (022) CL-B MCL-2ETH MODULE WAS INSERTED EVENT 07-05-2010 12:08:40",
"CLI MUX trap received: (090) IO-2 ML-1E1 EX1 LOST SIGNAL ON E1/T1 LINK OFF 04-06-2010 09:58:58",
"CLI MUX trap received: (094) IO-2 ML-1E1 EX1 CRC ERROR EVENT 04-06-2010 09:58:59",
"CLI MUX trap received: (009) CLK IS DIFF FROM MASTER CLK SRC OFF 07-05-2010 12:07:32",
};
for (String line : lines) {
System.out.println(line.substring(56, 94));
}
This prints:
MODULE WAS INSERTED EVENT
LOST SIGNAL ON E1/T1 LINK OFF
CRC ERROR EVENT
CLK IS DIFF FROM MASTER CLK SRC OFF
A regex solution
This is most likely not necessary, but something like this works (as seen on ideone.com):
line.replaceAll(".* \\b(.+ .+) \\S+ \\S+", "$1")
As you can see, it's not very readable, and you have to know your regex to really understand what's going on.
Essentially you match this to each line:
.* \b(.+ .+) \S+ \S+
And you replace it with whatever group 1 matched. This relies on the usage of two consecutive spaces exclusively for separating the columns in this table.
How about
.{56}(.*(EVENT|OFF))
Can you do field-oriented processing, rather than a regex? In awk/sh, this would look like:
< $datafile awk '{ print $(NF-3), $(NF-2) }' | column
which seems rather cleaner than specifying a regex.