Delphi search for text after a defined character - delphi

I have a string
String :='this is my string | yes';
I need delphi to get whatever the text is after the |
So something like:
getTextAftertoCharacter('|',String);
This should return "yes" in the example above.
Has Delphi get a function for this?

I'm not aware of a single function that does this. I think the easiest way would be to use Pos and then Copy:
answer := Copy(str, Pos('|', str) + 1, Length(str));
Start character is at Pos('|', str) + 1, amount of characters to copy is actually Length(str)-Pos('|', str), but passing a greater value to Copy also works.
Note: this will return the whole contents of str if there is no '|'. Check for Pos('|', str) being non-zero if you need different behavior.

You can use Controls.GetLongHint():
GetLongHint(String);
That's because the separator of a two part hint is a |. In your example it would return ' yes', with the leading space. If | is not found, the function returns the String.

I'd use then following code:
Trim(RightStr(Text, Length(Text)-LastDelimiter('|', Text)));
It'll locate the last delimiter in the string and I used Trim to get rid of the whitespace. LastDelimiter can take more than one delimiter which may be usefull. If no delimiter is found it will return the whole string.

Related

Lua string find - How to handle strings with a hyphen?

I have two strings - each string has many lines like the following:
string1 = " DEFAULT-VLAN | Manual 10.1.1.3 255.255.255.0 "
string2 = " 1 DEFAULT-VLAN | Port-based No No"
The first string I split into the following strings: "DEFAULT-VLAN", "|", "Manual"...
Then I want to look up the ID ("1") in string2 for the vlanName ("DEFAULT-VLAN") from string1.
I use this code to find the correct substring:
vpos1, vpos2 = vlan:find("%d-%s-" .. vlanName .. "%s-|")
But vpos1 and vpos2 are nil; When the hyphen ("-") is deleted from the vlanName it is working.
Shouldn't Lua take care to escape the special characters in such strings? The string is handed over from my C++ application to Lua and there may be lots of special characters.
Is there an easy way to solve this?
Thanks!
Lua is not magic. All the expression "%d-%s-" .. vlanName .. "%s-|" does is concatenate some strings, producing a final string. It has no idea what that string is intended to be used for. Only string.find knows that, and it can't have any affect on how the parameter it is given will be used.
So yes, vlanName will be interpreted as a Lua pattern. And if you want to use special characters, you will need to escape them. I would suggest using string.gsub for that. It'd be something like this:
vlanName:gsub("[%-...]", "%%%0")
Where ... are any other characters you want to escape.

Removing '#$A' from Delphi string

I am modifying a delphi app.In it I'm getting a text from a combo box. The problem is that when I save the text in the table, it contains a carriage return. In debug mode it shows like this.
newStr := 'Projector Ex320u-st Short Throw '#$A'1024 X 768 2700lm'
Then I have put
newStr := StringReplace(newStr,'#$A','',[rfReplaceAll]);
to remove the '#$A' thing. But this doesn't remove it.
Is there any other way to do this..
Thanks
Remove the quotes around the #$A:
newStr := StringReplace(newStr,#$A,'',[rfReplaceAll]);
The # tells delphi that you are specifying a character by its numerical code.
The $ says you are specifying in Hexadecimal.
The A is the value.
With the quotes you are searching for the presence of the #$A characters in the string, which aren't found, so nothing is replaced.
Adapted from http://www.delphipages.com/forum/showthread.php?t=195756
The '#' denotes an ASCII character followed by a byte value (0..255).
The $A is hexadecimal which equals 10 and $D is hexadecimal which equals 13.
#$A and #$D (or #10 and #13) are ASCII line feed and carriage return characters respectively.
Line feed = ASCII character $A (hex) or 10 (dec): #$A or #10
Carriage return = ASCII character $D (hex) or 13 (dec): #$D or #13
So if you wanted to add 'Ok' and another line:
Memo.Lines.Add('Ok' + #13#10)
or
Memo.Lines.Add('Ok' + #$D#$A)
To remove the control characters (and white spaces) from the beginning
and end of a string:
MyString := Trim(MyString)
Why doesn't Pos() find them?
That is how Delphi displays control characters
to you, if you were to do Pos(#13, MyString) or Pos(#10, MyString) then it
would return the position.

print carriage return (not line feed) in erlang?

Wondering if it's possible to print a carriage return without a line feed in erlang? i.e. equivalent to printf("this will be replaced next time \r"); in C.
Had a look through the io:format() documentation and didn't see anything. It only seems to support ~n, equivalent to carriage return+line feed pair ('\n' in C).
Thx.
"\r" is a perfectly valid escape sequence in Erlang. So you can do just
io:format("\r").
Check the reference manual for other escape sequences.
You can use \r in a string for the return character so:
io:format("Counter value: ~b\r", [Counter])
This is also works for character constants, $\r, and in quoted atoms.
Doh. Answer came almost as soon as I posted. ~c enables printing of ASCII characters, so it's just a case of printing ASCII carriage return (13). e.g.
io:format("Counter value: ~b~c", [Counter,13])
Still interested in anything more elegant...
Thx.

Regular expression in Ruby

Could anybody help me make a proper regular expression from a bunch of text in Ruby. I tried a lot but I don't know how to handle variable length titles.
The string will be of format <sometext>title:"<actual_title>"<sometext>. I want to extract actual_title from this string.
I tried /title:"."/ but it doesnt find any matches as it expects a closing quotation after one variable from opening quotation. I couldn't figure how to make it check for variable length of string. Any help is appreciated. Thanks.
. matches any single character. Putting + after a character will match one or more of those characters. So .+ will match one or more characters of any sort. Also, you should put a question mark after it so that it matches the first closing-quotation mark it comes across. So:
/title:"(.+?)"/
The parentheses are necessary if you want to extract the title text that it matched out of there.
/title:"([^"]*)"/
The parentheses create a capturing group. Inside is first a character class. The ^ means it's negated, so it matches any character that's not a ". The * means 0 or more. You can change it to one or more by using + instead of *.
I like /title:"(.+?)"/ because of it's use of lazy matching to stop the .+ consuming all text until the last " on the line is found.
It won't work if the string wraps lines or includes escaped quotes.
In programming languages where you want to be able to include the string deliminator inside a string you usually provide an 'escape' character or sequence.
If your escape character was \ then you could write something like this...
/title:"((?:\\"|[^"])+)"/
This is a railroad diagram. Railroad diagrams show you what order things are parsed... imagine you are a train starting at the left. You consume title:" then \" if you can.. if you can't then you consume not a ". The > means this path is preferred... so you try to loop... if you can't you have to consume a '"' to finish.
I made this with https://regexper.com/#%2Ftitle%3A%22((%3F%3A%5C%5C%22%7C%5B%5E%22%5D)%2B)%22%2F
but there is now a plugin for Atom text editor too that does this.

Funny CSV format help

I've been given a large file with a funny CSV format to parse into a database.
The separator character is a semicolon (;). If one of the fields contains a semicolon it is "escaped" by wrapping it in doublequotes, like this ";".
I have been assured that there will never be two adjacent fields with trailing/ leading doublequotes, so this format should technically be ok.
Now, for parsing it in VBScript I was thinking of
Replacing each instance of ";" with a GUID,
Splitting the line into an array by semicolon,
Running back through the array, replacing the GUIDs with ";"
It seems to be the quickest way. Is there a better way? I guess I could use substrings but this method seems to be acceptable...
Your method sounds fine with the caveat that there's absolutely no possibility that your GUID will occur in the text itself.
On approach I've used for this type of data before is to just split on the semi-colons regardless then, if two adjacent fields end and start with a quote, combine them.
For example:
Pax;is;a;good;guy";" so;says;his;wife.
becomes:
0 Pax
1 is
2 a
3 good
4 guy"
5 " so
6 says
7 his
8 wife.
Then, when you discover that fields 4 and 5 end and start (respectively) with a quote, you combine them by replacing the field 4 closing quote with a semicolon and removing the field 5 opening quote (and joining them of course).
0 Pax
1 is
2 a
3 good
4 guy; so
5 says
6 his
7 wife.
In pseudo-code, given:
input: A string, first character is input[0]; last
character is input[length]. Further, assume one dummy
character, input[length+1]. It can be anything except
; and ". This string is one line of the "CSV" file.
length: positive integer, number of characters in input
Do this:
set start = 0
if input[0] = ';':
you have a blank field in the beginning; do whatever with it
set start = 2
endif
for each c between 1 and length:
next iteration unless string[c] = ';'
if input[c-1] ≠ '"' or input[c+1] ≠ '"': // test for escape sequence ";"
found field consting of half-open range [start,c); do whatever
with it. Note that in the case of empty fields, start≥c, leaving
an empty range
set start = c+1
endif
end foreach
Untested, of course. Debugging code like this is always fun….
The special case of input[0] is to make sure we don't ever look at input[-1]. If you can make input[-1] safe, then you can get rid of that special case. You can also put a dummy character in input[0] and then start your data—and your parsing—from input[1].
One option would be to find instances of the regex:
[^"];[^"]
and then break the string apart with substring:
List<string> ret = new List<string>();
Regex r = new Regex(#"[^""];[^""]");
Match m;
while((m = r.Match(line)).Success)
{
ret.Add(line.Substring(0,m.Index + 1);
line = line.Substring(m.Index + 2);
}
(Sorry about the C#, I don't known VBScript)
Using quotes is normal for .csv files. If you have quotes in the field then you may see opening and closing and the embedded quote all strung together two or three in a row.
If you're using SQL Server you could try using T-SQL to handle everything for you.
SELECT * INTO MyTable FROM OPENDATASOURCE('Microsoft.JET.OLEDB.4.0',
'Data Source=F:\MyDirectory;Extended Properties="text;HDR=No"')...
[MyCsvFile#csv]
That will create and populate "MyTable". Read more on this subject here on SO.
I would recommend using RegEx to break up the strings.
Find every ';' that is not a part of
";" and change it to something else
that does not appear in your fields.
Then go through and replace ";" with ;
Now you have your fields with the correct data.
Most importers can swap out separator characters pretty easily.
This is basically your GUID idea. Just make sure the GUID is unique to your file before you start and you will be fine. I tend to start using 'Z'. After enough 'Z's, you will be unique (sometimes as few as 1-3 will do).
Jacob

Resources