How to set a variable with both single and double quotes? - coldfusion

How do I set a string variable in ColdFusion that uses a single quote and two double quotes within the string?
MyVar = "Include multiple addresses on "Recipient's E-Mail" separated by commas.";
I know I could break this up into several variables or escape some characters, but I am wondering if there is a standard "best" way, one that is concise and easy to read.
I could do it this way, but this is cumbersome:
// THIS WORKS
MyVar = "Include multiple addresses on ";
MyVar = MyVar & '"Recipient's E-Mail "';
MyVar = MyVar & "separated by commas.";
I should have noted that I am using CFSCRIPT within a function. This makes using savecontent bulky. And CF didn't like the name of my var (LOCAL.Info[i].EmailProd07) in savecontent, so I had to rename it.
// THIS WORKS
savecontent variable="LOCAL.MyVar" {
writeOutput("Multiple recipients may be included in ""Recipient's E-Mail"" separated by commas.");
};
LOCAL.Info[i].EmailProd07 = LOCAL.MyVar;
// THIS WORKS
LOCAL.Info[i].EmailProd07 = 'Multiple recipients may be included in "Recipient''s E-Mail" separated by commas.';

CF DOC:
Escaping quotation marks and number signs
To include a single-quotation character in a string that is
single-quoted, use two single-quotation marks (known as escaping the
single-quotation mark). The following example uses escaped
single-quotation marks:
<cfset myString='This is a single-quotation mark: '' This is a double-quotation mark: "'>
<cfoutput>#mystring#</cfoutput><br>
To include a double-quotation mark in a double-quoted string, use two
double-quotation marks (known as escaping the double-quotation mark).
The following example uses escaped double-quotation marks:
<cfset myString="This is a single-quotation mark: ' This is a double-quotation mark: """>
<cfoutput>#mystring#</cfoutput><br>
Because strings can be in either double-quotation marks or
single-quotation marks, both of the preceding examples display the
same text:
This is a single-quotation mark: ' This is a double-quotation mark: "
I would add:
<cfsavecontent variable="MyVar">
Include multiple addresses on "Recipient's E-Mail" separated by commas.
</cfsavecontent>
And if whitespace matters, either use trim() afterwards, or if the content is short, just keep the tag and content in one line with no whitespace in between.

MyVar = 'Include multiple addresses on "Recipient''s E-Mail" separated by commas.';
WriteOutput(MyVar);
The keys were:
Enclose string with single quotes to escape double quotes in the variable
Escape single quotes in variable with another single quote
Edit starts here
Here it is again, but with the single and double quotes switched.
MyVar = "Include multiple addresses on ""Recipient's E-Mail"" separated by commas.";
Works just as well

Couldn't you use the CHR function? http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_c-d_04.html
This would mean you simply replace one set of "'s with the correct character code instead.

you need to use the escape characters
usually it is : \
example :
string a = "bla bla bla \' dsfdsf \' bla "

Related

REGEX_TOO_COMPLEX error when parsing regex expression

I need to split the CSV file at commas, but the problem is that file can contain commas inside fields. So for an example:
one,two,tree,"four,five","six,seven".
It uses double quotes to escape, but I could not solve it.
I tried to use something like this with this regex, but I got an error: REGEX_TOO_COMPLEX.
data: lv_sep type string,
lv_rep_pat type string.
data(lv_row) = iv_row.
"Define a separator to replace commas in double quotes
lv_sep = cl_abap_conv_in_ce=>uccpi( uccp = 10 ).
concatenate '$1$2' lv_sep into lv_rep_pat.
"replace all commas that are separator with the new separator
replace all occurrences of regex '(?:"((?:""|[^"]+)+)"|([^,]*))(?:,|$)' in lv_row with lv_rep_pat.
split lv_row at lv_sep into table rt_cells.
You must use this Regex => ,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)
DATA: lv_sep TYPE string,
lv_rep_pat TYPE string.
DATA(lv_row) = 'one,two,tree,"four,five","six,seven"'.
"Define a separator to replace commas in double quotes
lv_sep = cl_abap_conv_in_ce=>uccpi( uccp = 10 ).
CONCATENATE '$1$2' lv_sep INTO lv_rep_pat.
"replace all commas that are separator with the new separator
REPLACE ALL OCCURRENCES OF REGEX ',(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)' IN lv_row WITH lv_rep_pat.
SPLIT lv_row AT lv_sep INTO TABLE data(rt_cells).
LOOP AT rt_cells into data(cells).
WRITE cells.
SKIP.
ENDLOOP.
Testing output
I never ever touched ABAP, so please see this as pseudo code
I'd recommend using a non-regex solution here:
data: checkedOffsetComma type i,
checkedOffsetQuotes type i,
baseOffset type i,
testString type string value 'val1, "val2, val21", val3'.
LOOP AT SomeFancyConditionYouDefine.
checkedOffsetComma = baseOffset.
checkedOffsetQuotes = baseOffset.
find FIRST OCCURRENCE OF ','(or end of line here) in testString match OFFSET checkedOffsetComma.
write checkedOffsetComma.
find FIRST OCCURRENCE OF '"' in testString match OFFSET checkedOffsetQuotes.
write checkedOffsetQuotes.
*if the next comma is closer than the next quotes
IF checkedOffsetComma < checkedOffsetQuotes.
REPLACE SECTION checkedOffsetComma 1 OF ',' WITH lv_rep_pat.
baseOffset = checkedOffsetComma.
ELSE.
*if we found quotes, we go to the next quotes afterwards and then continue as before after that position
find FIRST OCCURRENCE OF '"' in testString match OFFSET checkedOffsetQuotes.
write baseOffset.
ENDIF.
ENDLOOP.
This assumes that there are no quotes in quotes thingies. Didn't test, didn't validate in any way. I'd be happy if this at least partly compiles :)

Regular expression to split by whitespaces that are not inside double/single quotes?

If I have a string:
String string = "Hi my name is "Bob Peters""
I want to split the string by whitespaces only if it's not surrounded by quotes. But also, I don't want to include the quotes in my final result.
So the end result would be
Hi, my, name, is, Bob Peters
Where the name is together and the rest are split up.
In groovy, here is what I have so far:
def text = "Hi my name is 'Bob Peters'"
def newText = text.split(/\s(?=(?:[^'"`]*(['"`])[^'"`]*\1)*[^'"`]*$)/);
println(newText)
this results in
Hi
my
name
is
`Bob Peters`
But I need to be able to remove the single/double quotes surrounding Bob Peters too
The simplest options is to have an additional step to remove the quotes, as below
​def text = "'Hi there' my name is 'Bob Peters' 'Additional quotes'"
def newText = text.split(/\s(?=(?:[^'"`]*(['"`])[^'"`]*\1)*[^'"`]*$)/);
print(newText.collect {
it.replaceAll(/^['"`](.*)['"`]$/,'$1');
})
It would print [Hi there, my, name, is, Bob Peters, Additional quotes]
Alternatively, we can consider a space optionally preceded and followed by quotes ['"`] as split pattern.
But this will not remove quotes at the start and end of the string. We need to include alternate split pattern to include quotes at the start and end of string.
So the pattern becomes
^['"`]|['"`]$|['"`]?<<< Your Existing Pattern >>>['"`]?.
There is one another issue with this approach. If quotes appear at the start of the string like 'Hi there ...```, then an empty string will be prepended in the output.
So we will include a space at the beginning of the string and always ignore the first element in the result array. The final patter will be
^\s['"`]|['"`]$|['"`]?<<<Your Existing Pattern>>>['"`]?
Groovy Code:
def text = "Hi there my name is 'Bob Peters' 'Additional quotes'"
def newText = (" " + text).split(/^\s['"`]|['"`]$|['"`]?\s(?=(?:[^'"`]*(['"`])[^'"`]*\1)*[^'"`]*$)['"`]?/);
print(newText[1..newText.size()-1])​
Will print [Hi, there, my, name, is, Bob Peters, Additional quotes]
Note: The positive lookahead, \s(?=(?:[^'"`]*(['"`])[^'"`]*\1)*[^'"`]*$) will not handle nested quotes. Example
Hi there `Outer quotes 'inner quotes'`
will not be split.

Replace double quoted strings by single quoted except for GStrings

My OCD has gotten the better of me and I'm going through my groovy codebase replacing simple strings with double quotes around them into single quoted strings.
However, I want to avoid GStrings that actually contain dollar symbols and variables.
I'm using IntelliJ to do the substitution, and the following almost works:
From: "([^$\"\n\r]+)"
To: '$1'
It captures strings without any dollars in, but only partially skips any strings that contain them.
For example it matches the quotes between two double quoted strings in this case:
foo("${var}": "bar")
^^^^
Is it possible to create a regex that would skip a whole string that contained dollars, so in the above case it skips "${var}" and selects "bar", instead of erroneously selecting ": "?
EDIT: Here's a section of code to try against
table.columns.elements.each{ columnName, column ->
def columnText = "${columnName} : ${column.dataType}"
cols += "${columnText}\n"
if (columnText.length() > width) {
width = columnText.length()
}
height++
}
builder."node"("id": table.elementName) {
builder."data"("key": "d0") {
builder."y:ShapeNode"()
}
}
def foo() {
def string = """
a multiline quote using triple quotes with ${var} gstring vars in.
"""
}
Do single and triple quote replacements separately.
Single quotes:
Use a look ahead for an even number of quotes after your hit. A negative look behind stops it matching the inner quotes of triple quoted strings.
Find: (?<!")"([^"$]*)"(?=(?:(?:[^"\r\n]*"){2})*[^"]*$)
Replace: '$1'
See live demo.
Triple quotes:
Use a simpler match for triple quoted strings, since they are on their own lines.
Find: """([^"$]*?)"""
Replace: '''$1'''
See live demo, which includes a triple-quoted string that contains a variable.
You need to make sure the first quote comes after even number of quotes:
^[^\n\r"]*(?:(?:"[^"\n\r]*){2})*"([^$\"\n\r]+)"
Here you can play with it.
Explanation:
^[^"\n\r]* - some non-quotes at the beginning
"[^"\n\r]* - a quote, then some more non-quotes
(?:"[^"\n\r]*){2} - let's have two of this
(?:(?:...)) - actually, let's have 0, 2, 4, 6, ... whatever amount of this
Then your regex comes to match the right string: "([^$\"\n\r]+)"
If intellij supports that, then you can make it faster by replacing the non-capturing groups (?:...) with atomic groups (?>...).
This regex finds the last string in the line so you'll have to run the replace several times.
Update
Updated the negated character classes with the newline characters. Now it works well for multi-line texts too. Still, you'll have to run it several times because it finds only one string per line.

How to use regex to replace all semicolons inside double quoted strings by spaces?

I need to replace all semicolos ; in lines of a file by a space character only when the semicolon is between double quotation marks " ".
For example the following line
'in this area the semicolon should not be replaced "however in this area it ; should be" other text "another ; text" ;....'crlf
should be modified to
'in this area the semicolon should not be replaced "however in this area it should be" other text "another text" ;....'crlf
using regular expression.
I succeeded only on replacing all text between quotation marks with nothing, i.e. to delete the double quoted text.
This is what I used in ColdFusion language:
<cfset newline=rereplace(line,'\"[^\"]*\"','','all')>
Has anyone an idea how can I use regex to replace only the semicolon character by a space when it is positioned between quotation marks?
You may use the below regex..
<cfset newline=rereplace(line,';(?!(?:\"[^\"]*\"|[^\"])*$)',' ','all')>

Regex Replace A Variable Within Brackets, Including Brackets

How do I get rid of a variable within square brackets, including the brackets themselves? E.g. [152] or [153] or [154]. I am using Yahoo Pipes.
You can escape the brackets (like any other character with a special meaning) with \.
s/\[\d+\]/Replacement/
In Yahoo Pipes it should work like: replace \[.+\] with (leave blank). Maybe you have to check the g flag.
I am unsure if the variables will always be numbers my solutions works by removing all occurrences of [anything]
replace
\[[^\]]*\] with ""
javascript example
var s = "[152] xxx [153]zzz [154] i";
s = s.replace(/\[[^\]]*\]/g,'')
s ; //# => xxx zzz i
try
var rx= '/[\[\.*\]]/g';
var s = "[152] [153] [154] ";
s.replace(rx,'');
DEMO