unexpected behavior with replaceList function - coldfusion

We recently moved from CF 10 to CF 2016 and stumbled upon the following issue:
<cfscript>
x = "abc";
x = replaceList(x, "ab|cd", "1|2", "|");
writeDump(x);
// CF 11, CF 2016
// >> 12
// CF 10, Railo/Lucee
// >> 1c
// --------------------
x = "abc";
x = replaceList(x, "ab,cd", "1,2", ",");
writeDump(x);
// CF 11, CF 2016
// >> 1c
// CF 10, Railo/Lucee
// >> 1c
</cfscript>
What is going on here? Why is this change not documented by Adobe? Is it even an intended change to begin with?
Update:
Bug Report #4164200 filed with Adobe

Short answer:
I suspect it is unintentional and would file a bug report. As a work around, try escaping the pipe symbol: replaceList(x, "ab|cd", "1|2", "\|");.
Longer answer:
Internally, this function would almost certainly use some sort of regular expression ( where pipe symbols | have a special meaning ie logical OR). My guess is that CF first uses String.split("regex") to break the two lists into arrays. Then loops through the arrays to perform the replacements.
Based on the results, CF is not escaping the pipe symbol, causing the lists to be split differently than expected. Each individual character becomes a separate element, which obviously ends up matching more than you intended ie every character in the base string.
list = "ab|cd";
writeDump(list.split("|") );
However, if you escape the pipe symbol with \, you get the expected results:
list = "ab|cd";
writeDump(list.split("\|"));

Related

COGNOS 11 Concatenate with cast for char length

Probably simple but my head is fried right now with figures. I'm using COGNOS 11 and trying to make a data item display character length of '4' i.e 0014 rather than just 14. I can do this in the edit within the report properties but I'm trying to do a concatenate string and it keeps reverting to 14.
I've been trying CAST([Demand No], varchar(4)) as the expression definition (comes up as 'No error') but it still keeps dropping the leading 00 on the report.
My full concatenated string so far [Unit ID]||to_char(cast([Demand Date],date), 'ddmmyyyy')||cast([Demand No], varchar(4)). This produces XXXXXXDDMMYYYY0000 but only when the last four characters are 0000 but it looks like this XXXXXXDDMMYYYY00 if the leading 0's are dropped.
You could try lpad(cast([Demand No], varchar(4)),2,'0')
Not elegant, but this uses generic Cognos functions:
substring('0000', 1, 4 - char_length(cast([Demand No], varchar(4)))) || cast([Demand No], varchar(4))

Jmeter Regular Expression Extractor. How to save all returned values to a single variable?

I'm quite new to Jmeter and already spent numerous hours to figure it out.
What i'm trying to achieve:
Using Post Processor Regex Extractor I wrote a regex that returns me several values (already tested it in www.regex101.com and it's working as expected). However, when I do this in Jmeter, I need to provide MatchNo. which in this case will only return to me one certain value. I sort of figured it out that negative digit in this field (Match No) suppose to return all values found. When I use Debug Sampler to find out how many values are returned and to what variables they are assigned, I see a lot of unfamiliar stuff. Please see examples below:
Text where regex to be parsed:
some data here...
"PlanDescription":"DF4-LIB 4224-NNJ"
"PlanDescription":"45U-LIP 2423-NNJ"
"PlanDescription":"PMH-LIB 131-NNJ"
some data here...
As I said earlier, at www.regex101.com I tested this with regex:
\"PlanDescription\":\"([^\"]*)\"
And all needed for me information are correct (with the group 1).
DF4-LIB 4224-NNJ
45U-LIP 2423-NNJ
PMH-LIB 131-NNJ
With the negative number (I tried -1, -2, -3 - same result) at MatchNo. field in Jmeter Regex Extractor field (which Reference Name is Plans) at the Debug Sampler I see the following:
Plans=
Plans_1=DF4-LIB 4224-NNJ
Plans_1_g=1
Plans_1_g0="PlanDescription":"DF4-LIB 4224-NNJ"
Plans_1_g1=DF4-LIB 4224-NNJ
Plans_2=45U-LIP 2423-NNJ
Plans_2_g=1
Plans_2_g0="PlanDescription":"45U-LIP 2423-NNJ"
Plans_2_g1=45U-LIP 2423-NNJ
Plans_3=PMH-LIB 131-NNJ
Plans_3_g=1
Plans_3_g0="PlanDescription":"PMH-LIB 131-NNJ"
Plans_3_g1=PMH-LIB 131-NNJ
I only need at this particular case - Jmeter regex to return 3 values that contain:
DF4-LIB 4224-NNJ
45U-LIP 2423-NNJ
PMH-LIB 131-NNJ
And nothing else. If anybody faced that problem before any help will be appreciated.
Based on output of the Debug Sampler, there's no problem, it's just how RegEx returns the response:
Plans_1,Plans_2,Plans_3 is the actual set of variables you wanted.
There should also be Plans_matchNr which should contain the number of matches (3 in your example). It's important if you loop through them (you will loop from 1 to the value of this variable)
_g sets of variables refer to matching groups per matching instance (3 in your case). Ignore them if you don't care about them. They are always publish, but there's no harm in that.
Once variables are published you can do a number of things:
Use them as ${Plans_1}, ${Plans_2}, ${Plans_3} etc. (as comment above noticed).
Use Plans_... variables in loop: refer to the next variable in the loop as ${__V(Plans_${i})}, where i is a counter with values between 1 and Plans_matchNr
You can also concatenate them into 1 variable using the following simple BeanShell Post-Processor or BeanShell Sampler script:
int count = 0;
String allPlans = "";
// Get number of variables
try {
count = Integer.parseInt(vars.get("Plans_matchNr"));
} catch(NumberFormatException e) {}
// Concatenate them (using space). This could be optimized using StringBuffer of course
for(int i = 1; i <= count; i++) {
allPlans += vars.get("Plans_" + i) + " ";
}
// Save concatenated string into new variable
vars.put("AllPlans", allPlans);
As a result you will have all old variables, plus:
AllPlans=DF4-LIB 4224-NNJ 45U-LIP 2423-NNJ PMH-LIB 131-NNJ

Unicode string extraction and comparison

1.val Matcher = """.+/(.*)""".r
2.val Matcher(title) = """http://en.wikipedia.org/wiki/Château_La_Louvière"""
3.val lowerCase = title.toLower
4.if(lowercase.equals("château_la_louvière")) //do something
The above comparison returns false because I guess line 2 results in Ch?teau_La_Louvi?re. Any ideas how I can accomplish this?
As 4e6 says the problem lies within the standard configuration of Java. Which assumes all files encoded in Latin1.
1.val Matcher = """.+/(.*)""".r
2.val Matcher(title) = """http://en.wikipedia.org/wiki/Château_La_Louvière"""
This could be fixed by setting the following java-OPTS
export JAVA_OPTS='-Dfile.encoding=UTF-8'
Still 1. and 2. will work, even if you don't change the encoding. The Problem lies in 3. and 4. .
3.val lowerCase = title.toLower
4.if(lowercase.equals("château_la_louvière")) //do something
''toLower'' will cause the test in 4. to fail , because "â" and "è" will be interpreted wrongly. These characters would be encoded as two up to four bytes, which each will be lowercased independently thus yielding a completely different result as ''château_la_louvière'' .

C++ parsing as custom language Interpreter

I need to parse input text file as custom language that i should interpret it's commands (line by line) and execute it, that's the input i should expect:
#Some variables
myInt = 2
myFloat = 2.5
myString = “Hello”
#Lists
myList = (myInt, myFloat, myInt + myFloat)
myOtherList = (myFloat + myFloat, myInt+ myInt)
subList = myList[:1]
completeList = myList + myOtherList + subList
#This should have no effect (it is ok if it is being calculated)
2+4
#Now some printing
print(myString)
print(“World”)
print(completeList)
print(completeList[3])
#Some syntax errors
b = “hello, this string is not enclosed right
c = myString + completeList
d = myInt + SOME_VARIABLE_I_HAVENT_DEFINED_YET
#First string to appear makes everything a string
print(1 + 2 + 15.5 + 2.2 + “Hi” + 3 + 4 + 6)
print(1 + 2 + 15.5 + 2.2 + 3 + 4 + 6 + “hi”)
print((1,2))
So I already have a first checking function, now I know when it's print/assign/comment/bad syntax command or whatever. I now should parse what inside the print function and the assign commands, I should ignore white spaces, they also might not be as delimiters to count on.
Please guide me a bit, what string functions i should use and how in order to to make it work, I mean how you can cut to tokens and also identify the mathematical signs? I'm guessing it should use some stack to follow the parentheses of the list type and quotation signs, no? Any general and more detailed information will be appreciated, thanks(:
p.s.
That's the output for this code:
Hello
World
(2, 2.5, 4.5, 5.0, 4, 2, 2.5)
5.0
InvalidSyntax : b = “hello, this string is not enclosed right
InvalidSyntax : c = myString + completeList
UndefinedVariableName : SOME_VARIABLE_I_HAVENT_DEFINED_YET
20.7Hi346
33.7hi
(1,2)
I already have all the overloading operators for what I need, I only need to parse it right and send it to my already built functions.
So you haven't had a chance to read the Dragon Book...
How do you think about embedding Lua or Python interpreter into your product, instead of inventing your own language? They are more common and full-fledged programming languages. Moreover Google will help you find lots of tutorials on how to embed them, such as:
http://docs.python.org/extending/embedding.html
http://www.ibm.com/developerworks/linux/library/l-embed-lua/
The disadvantage of inventing your own language is that: even after you successfully parsed your own language, you need to define semantics for it. Parsing only deals with the syntax, which is a different thing from the semantics. I don't know your situation but both of them usually require too long time to learn for just a single software project.
As for Boost Spirit: I don't recommend to use it which was written by people who just wanted to show their smartness by writing it (but in the end showed their ignorance about what is practical software design.)
A wonderful C++ library exists for that : SPIRIT

Bison does not appear to recognize C string literals appropriately

My problem is that I am trying to run a problem that I coded using a flex-bison scanner-parser. What my program is supposed to do is take user input (in my case, queries for a database system I'm designing), lex and parse, and then execute the corresponding actions. What actually happens is that my parser code is not correctly interpreting the string literals that I feed it.
Here's my code:
130 insertexpr : "INSERT" expr '(' expr ')'
131
132 {
133 $$ = new QLInsert( $2, $4 );
134 }
135 ;
And my input, following the "Query: " prompt:
Query: INSERT abc(5);
input:1.0-5: syntax error, unexpected string, expecting end of file or end of line or INSERT or ';'
Now, if I remove the "INSERT" string literal from my parser.yy code on line 130, the program runs just fine. In fact, after storing the input data (namely, "abc" and the integer 5), it's returned right back to me correctly.
At first, I thought this was an issue with character encodings. Bison code needs to be compiled and run using the same encodings, which should not be an issue seeing as I am compiling and running from the same terminal.
My system details:
Ubuntu 8.10 (Linux 2.6.24-16-generic)
flex 2.5.34
bison 2.3
gcc 4.2.4
If you need any more info or code from, let me know!
This is a classic error, if you use flex to lex your input into tokens, you must not refer to the literal strings in the parser as literal strings, but rather use tokens for them.
For details, see this similar question
Thankee, thankee, thankee!
Just to clarify, here is how I implemented my solution, based on the comments from jpalecek. First, I declared an INSERT token in the bison code (parser.yy):
71 %token INSERT
Next, I defined that token in the flex code (scanner.ll):
79 "INSERT INTO" { return token::INSERT; }
Finally, I used the token INSERT in my grammar rule:
132 insertexpr : INSERT expr '(' expr ')'
133
134 {
135 $$ = new QLInsert( $2, $4 );
136 }
137 ;
And voila! my over-extended headache is finally over!
Thanks, jpalecek :).