Regex is working in regex101.com but not in google scripts - regex

The problem:
I had a similar problem to this thread - my Regex works like a charm in regex101, but returns null in google scripts.
I'm trying to return the next line on a number of items:
Confirmation code
Check-in
Checout
Payout
Number of Guest
Payout
Here is the data I am searching in:
New booking confirmed!Jake arrives Oct 22
Send a message to confirm check-in details or welcome Jake.
Jake Flake
Phoenix, California, United States
Airbnb member since 2015
Send Jake a message:
https://www.airbnb.com/z/q/;laskdf;lksjdf
The Getaway
https://www.airbnb.com/manage-listing/asdflkjsdf;lkajsfd
Trip details
Check-in
Sun, Oct 22
Anytime after 4PM
Checkout
Thu, Oct 26
11AM
Guests
13
Confirmation code
H7XS0SA8
View itinerary
https://www.airbnb.com/reservation/itinerary?code=aasdfasdf
Payment
$275.50 x 4 nights
$1102.00
Cleaning Fees
$180.00
Guest Pays
$1282.00
Airbnb Fees
-$38.46
You earn
$1243.54
On the day after your guest checks in, the payment method you supplied will be credited. For details, see your transaction history.
Your guest paid $161.15 in Occupancy Taxes. Airbnb remits these taxes on your behalf.
Get ready for Jake’s arrival
Provide Directions
Confirm that your guest knows how to get to your place.
Tidy Up
Clean up all shared spaces. Make sure your guest has clean linens and towels.
Customer Support
Visit Help Center
https://www.airbnb.com/help?eal_exp=asdfasdf
Contact Airbnb
https://www.airbnb.com/help/contact_us?eal_exp=asdfasdf
Thanks,
The Airbnb Team
Email preferences
https://www.airbnb.com/users/notifications?eal_exp=asdfasdf
Airbnb
My code that works:
function getNumberofGuests(message_body) {
var num_guests = message_body.match("Guests[\r\n]+([^\r\n]+)")[1];
Logger.log("num_guests: " + num_guests);
return num_guests;
}
Logs -- num_guests: 13
The same code in a similar senario that doesn't work:
function getReservationID(message_body) {
var reservationID = message_body.match("Confirmation\scode[\r\n][^\r\n]+")[1];
Logger.log("reservationID: " + reservationID);
return reservationID;
Logs -- reservationID: null
PS
The formatting of the body in this display is off for some reason, and I tried for 30 minutes but still couldn't fix it. In the message_body, it should be a new line after "Check-in", "Checkout", "Guests", "Confirmation code", etc. - there is a new line after every element that is currently showing a space.
I also tried the space character regex, and still got null:
var regExp = new RegExp("Confirmation\scode[\s]^[^\s]+", 'g')

After taking a look at the code and trying it out, you're getting the null because of what you changed in the match method. The reason why num_guests works is because that it's set up in a way that looks for the word "Guests" and the next line is the result from the array (notice the [1] on the end of the line). That same concept/regex works for the confirmation code portion as well, but you put in the "\s" and changed the order of some parentheses. Since the search code is in double quotes, you don't need the "\s". Basically, you have "Confirmation\scode" when you want "Confirmation code". Although it works in regex101, trying in the Google Apps Script environment will produce actual results.

I loaded the data into a file and then loaded the file into variable dt in the following code:
function getMyData()
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet()
var dt=myUtilities.loadFile('regex.txt');
var guests = dt.match(/^Guests (\d+)/m)[1];
var cf=dt.match(/^Confirmation code ([0-9A-Z]+)/m)[1];
var ui=HtmlService.createHtmlOutput(dt).append(Utilities.formatString('<br /><strong>Matches:</strong><br />Guests=%s<br />Confirmation Code=%s',guests,cf));
SpreadsheetApp.getUi().showModelessDialog(ui, 'Input Data & Extracted Parameters');
}
After playing with the regexs for a while I got this output which includes a copy of the data:
(The m flag is for multiline).
I missed some of the data the first time around.
Here's the new code with some of your additional parameters:
function getMyData()
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet()
var dt=myUtilities.loadFile('regex.txt');
var guests = dt.match(/^Guests (\d+)/m)[1];
var cf=dt.match(/^Confirmation code ([0-9A-Z]+)/m)[1];
var chout=dt.match(/^Checkout (.*)$/m)[1];
var chin=dt.match(/^Trip details (.*)$/m)[1];
var payout=dt.match(/Guest Pays ([$.0-9]+)/m)[1];
var ui=HtmlService.createHtmlOutput(dt).append(Utilities.formatString('<br /><strong>Matches:</strong><br />Guests=%s<br />Confirmation Code=%s<br />Checkout=%s<br />Checkin=%s<br />Payout=%s',guests,cf,chout,chin,payout)).setWidth(1200);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Input Data and Extracted Parameters');
}
And here's the output:
I'm guessing that you can figure out how to get the rest of them yourself.

Related

AWS SES does not correctly display two code point emojis

I am doing the following for a subject of an email for AWS SES:
private static final String US_FLAG_STRING = String.valueOf(Character.toChars(127482))
+ String.valueOf(Character.toChars(127480));
StringBuilder sbTitle = new StringBuilder();
sbTitle.append("Test title ").append(US_FLAG_STRING).append(" ").append(getWeekPartOfTitle(now));
When sending the aws SES request I use:
.withSubject(new Content()
.withCharset("UTF-8").withData(emailDetails.getSubject())))
But my output when I get my test email is 'Test title ??🇸 August 26 - September 2', which is not the American Flag. Does anyone know how to get two-code-point emojis to appear correctly?
Note that when I use a static string (without making the string dynamic) then it works, which I find odd. I know that Strings in java are immutable, so it must be making a copy, but I do not know how to fix it to work...

IBM Watson Alchemy news iOS SDK Swift

The IBM Watson iOS SDK using the Alchemy News service on Bluemix returns a string result which requires parsing to pull out the fields like url and cleaned title. ref: https://github.com/watson-developer-cloud/swift-sdk
I pull the string into an array and parse it in swift3 using some string methods but this is pretty ordinary and can produce unpredictable results
Is there a more elegant approach where I can access specific fields, like the url and cleaned title which I am passing to a UITableViewCell to select and segue to the url link.
sample code:
let alchemyDataNews = AlchemyDataNews(apiKey: apiKey)
let failure = { (error: Error) in print(error) }
let start = "now-14d" // 7 day ago
let end = "now" // today
let query = ["count": "15",
"dedup": "true",
"q.enriched.url.title": "[IBM]",
"return": "enriched.url.url,enriched.url.title" "enriched.url.title,enriched.url.entities.entity.text,enriched.url.entities.entity.type"]
Also I have noticed the search string [IBM] has a prefix of 0, i.e. 0[IBM] and have also seen an "A". What do these prefixes mean and where are they documented
Here is one way you can access the fields from a returned payload.
alchemyDataNews.getNews(from: "now-4d", to: "now", query: queryDict, failure: failWithError) { news in
for doc in (news.result?.docs)! {
var cleanedTitle = doc.source?.enriched?.url?.cleanedTitle
var author = doc.source?.enriched?.url?.author
var title = doc.source?.enriched?.url?.title
}}
Also, here is a nice API reference link for alchemy data which contains all of the request parameters and filters.
https://www.ibm.com/watson/developercloud/alchemydata-news/api/v1/

Meteor regex find() far slower than in MongoDB console

I've been researching A LOT for past 2 weeks and can't pinpoint the exact reason of my Meteor app returning results too slow.
Currently I have only a single collection in my Mongo database with around 2,00,000 documents. And to search I am using Meteor subscriptions on the basis of a given keyword. Here is my query:
db.collection.find({$or:[
{title:{$regex:".*java.*", $options:"i"}},
{company:{$regex:".*java.*", $options:"i"}}
]})
When I run above query in mongo shell, the results are returned instantly. But when I use it in Meteor client, the results take almost 40 seconds to return from server. Here is my meteor client code:
Template.testing.onCreated(function () {
var instance = this;
// initialize the reactive variables
instance.loaded = new ReactiveVar(0);
instance.limit = new ReactiveVar(20);
instance.autorun(function () {
// get the limit
var limit = instance.limit.get();
var keyword = Router.current().params.query.k;
var searchByLocation = Router.current().params.query.l;
var startDate = Session.get("startDate");
var endDate = Session.get("endDate");
// subscribe to the posts publication
var subscription = instance.subscribe('sub_testing', limit,keyword,searchByLocation,startDate,endDate);
// if subscription is ready, set limit to newLimit
$('#searchbutton').val('Searching');
if (subscription.ready()) {
$('#searchbutton').val('Search');
instance.loaded.set(limit);
} else {
console.log("> Subscription is not ready yet. \n\n");
}
});
instance.testing = function() {
return Collection.find({}, {sort:{id:-1},limit: instance.loaded.get()});
}
And here is my meteor server code:
Meteor.publish('sub_testing', function(limit,keyword,searchByLocation,startDate,endDate) {
Meteor._sleepForMs(200);
var pat = ".*" + keyword + ".*";
var pat2 = ".*" + searchByLocation + ".*";
return Jobstesting.find({$or:[{title:{$regex: pat, $options:"i"}}, { company:{$regex:pat,$options:"i"}},{ description:{$regex:pat,$options:"i"}},{location:{$regex:pat2,$options:"i"}},{country:{$regex:pat2,$options:"i"}}],$and:[{date_posted: { $gte : endDate, $lt: startDate }},{sort:{date_posted:-1},limit: limit,skip: limit});
});
One point I'd also like to mention here that I use "Load More" pagination and by default the limit parameter gets 20 records. On each "Load More" click, I increment the limit parameter by 20 so on first click it is 20, on second click 40 and so on...
Any help where I'm going wrong would be appreciated.
But when I use it in Meteor client, the results take almost 40 seconds to return from server.
You may be misunderstanding how Meteor is accessing your data.
Queries run on the client are processed on the client.
Meteor.publish - Makes data available on the server
Meteor.subscribe - Downloads that data from the server to the client.
Collection.find - Looks through the data on the client.
If you think the Meteor side is slow, you should time it server side (print time before/after) and file a bug.
If you're implementing a pager, you might try a meteor method instead, or
a pager package.

IF Function - Google Scripts

I'm struggling to get my Script to run an IF function. Basically I want to run a script based on specific cell contents.
I would like an IF function to run based on this and have written the following code:
function sendemail () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = SpreadsheetApp.getActiveSheet();
var targetSheet = ss.getSheetByName("Response");
var vCodes = ss.getSheetByName("Codes")
var vResults = targetSheet.getRange("E2").getValues();
var emailAddresses = targetSheet.getRange("B2").getValues()
var dataRange = vCodes.getRange(1, 1, vResults, 1).getValues();
var subject = "Here are your Wi-Fi Codes!";
var vLength = vCodes.getRange("C2").getValues();
if (vLength == "24 hours"){
MailApp.sendEmail(emailAddresses, subject, dataRange);
targetSheet.deleteRows(2);
vCodes.deleteRows(1,vResults);
}
}
If the value in C2 is "24 hours" I'd like it to send an e-mail. At the moment when I run the script there are no errors but it doesn't send any e-mail as the IF function obviously isn't running correctly.
If I edit the code to say:
if (vLength == "")
then the e-mail sends. It doesn't seem to recognise "24 hours" as valid data to look up.
Can anyone see what I'm doing wrong?
The value you get from the cell is not what you think because you are using getValues() with an 's' and you probably know that this method always returns an array of arrays, even when a single cell is defined as range.
You have 2 options :
use getValue() to get the string content of the cell
use getValues()[0][0] to get the first (and only) element of this array.
I would suggest the first solution as I think it's generally a good idea to use appropriate methods... getValue() for single cell and getValues() for multiple cells...
I didn't check further but I'm pretty sure it will work with this change (applies to vResults , emailAddresses and vLength) .
It would also be careful to ensure that vResults is a number since you use it to define a range... you could use Number(vResults) as a safety measure.

How do I set cookies for individual pages for use with colorbox?

I have been using a script with colorbox that writes a cookie when a page is visited and only opens the colorbox on page load if the page has not been visited in the last month.
I would now like to amend this so that it writes and checks for a cookie for the specific page rather than the domain as a whole. This is because I am publishing a new page each month and would like a colorbox to open the first time a user visits the new page each month. Here is the script as it currently stands:
if (document.cookie.indexOf('visited=true') === -1) {
var expires = new Date();
expires.setDate(expires.getDate()+31);
document.cookie = "visited=true; expires="+expires.toUTCString();
$.colorbox({href:'welcome.html', width:"60%", speed:1500});
}
Could someone help me adapt this to work on a page-by-page basis,
Thanks,
Nick
I figured out how to do this:
I changed this line:
document.cookie = "visited=true; expires="+expires.toUTCString();
to this:
document.cookie = "visited=true; path=/page.php; expires="+expires.toUTCString();