require solution for string replacement - ruby

I have a code where I have to replace a string with another string.
My file contains
secondaryPort = 7504
The code below
filtered_data =
filtered_data.gsub(
/secondaryPort=\d+/,
'secondaryPort=' + node['server']['secondaryPort']
)
should replace my file with
secondaryPort = 7555
but it fails to do so.

Make sure you account for the spaces around the equals sign in your string:
filtered_data = 'secondaryPort = 7504'
=> 'secondaryPort = 7504'
# with literal spaces
filtered_data.gsub(/secondaryPort = \d+/, 'secondaryPort = 7555')
=> 'secondaryPort = 7555'
# with regex character class for literal space
filtered_data.gsub(/secondaryPort\s{1}=\s{1}\d+/, 'secondaryPort = 7555')
=> 'secondaryPort = 7555'

Related

Is there a way to simply replace string elements containing escape characters

From a file i import lines. In this line an (escaped) string is part of the line:
DP,0,"021",257
DP,1,"022",257
DP,2,"023",513
DP,3,"024",513
DP,4,"025",1025
DP,5,"026",1025
DP,6,"081",257
DP,7,"082",257
DP,8,"083",513
DP,9,"084",513
DP,10,"085",1025
DP,11,"086",1025
DP,12,"087",1025
DP,13,"091",257
DP,14,"092",513
DP,15,"093",1025
IS,0,"FIX",0
IS,1,"KARIN02",0
IS,2,"KARUIT02",0
IS,3,"KARIN02HOV",0
IS,4,"KARUIT02HOV",0
IS,5,"KARIN08",0
IS,6,"KARUIT08",0
IS,7,"KARIN08HOV",0
IS,8,"KARUIT08HOV",0
IS,9,"KARIN09",0
IS,10,"KARUIT09",0
IS,11,"KARIN09HOV",0
IS,12,"KARUIT09HOV",0
IS,13,"KARIN10",0
IS,14,"KARUIT10",0
IS,15,"KARIN10HOV",0
I get the following Objects (if DP) :
index - parts1 (int)
name - parts2 (string)
ref - parts3 (int)
I tried using REGEX to replace the excape-sequence from the lines but to no effect
#name_to_ID = {}
kruising = 2007
File.open(cfgFile).each{|line|
parts = line.split(",")
if parts[0]=="DP"
index = parts[1].to_i
hex = index.to_s(16).upcase.rjust(2, '0')
cname = parts[2].to_s
tname = cname.gsub('\\"','')
p "cname= #{cname} (#{cname.length})"
p "tname= #{tname} (#{tname.length})"
p cname == tname
#name_to_ID[tname] = kruising.to_s + "-" + hex.to_s
end
}
teststring = "021"
p #name_to_ID[teststring]
> "021" (5)
> "021" (5)
> true
> nil
The problem came to light when calling from another string reference (length3)
hash[key] isnt equal as string "021" ( length 5) is not string 021 ( length 3)
any method that actually replaces the chars i need?
EDIT: I used
cname.each_char{|c|
p c
}
> "\""
> "0"
> "2"
> "1"
> "\""
EDIT: requested outcome update:
# Current output:
#name_to_ID["021"] = 2007-00 "021".length = 5
#name_to_ID["022"] = 2007-01 "022".length = 5
#name_to_ID["081"] = 2007-06 "081".length = 5
#name_to_ID["082"] = 2007-07 "082".length = 5
#name_to_ID["091"] = 2007-0D "091".length = 5
#name_to_ID["101"] = 2007-10 "101".length = 5
# -------------
# Expected output:
#name_to_ID["021"] = 2007-00 "021".length = 3
#name_to_ID["022"] = 2007-01 "022".length = 3
#name_to_ID["081"] = 2007-06 "081".length = 3
#name_to_ID["082"] = 2007-07 "082".length = 3
#name_to_ID["091"] = 2007-0D "091".length = 3
#name_to_ID["101"] = 2007-10 "101".length = 3
Your problem is you don't know the correct character in your string. It might not be the same character when printing it.
Try parts[2].to_s.bytes to check exactly what is the character code of that unexpected character. For example:
> "͸asd".bytes
=> [205, 184, 97, 115, 100]
Alternatively, you can delete the first and the last characters, if you are sure that every part of the string has the same format:
cname = parts[2].to_s[1..-2]
Or you can remove all special characters in the string if you know that the string will not contain any special character
cname = parts[2].to_s.gsub(/[^0-9A-Za-z]/, '')

two regex tests within regex

now i have got a problem with preg_match.
This is an example string: "!asksheet!H69=var8949", there can also be more than one var8949 or H69 index in this row. Result shoud be "var33333=var8949"
This is my part:
preg_match_all('#\b\!(.*)\![A-Z]{1,3}\d+\b#', $output, $matches2);
foreach ($matches2[0] as $match2) {
$result6 = $db->query("SELECT varid FROM variablen WHERE varimportedindex = '".$match2."' AND projectid = $pid AND varsheetname LIKE '%".$match2."%' ");
$rowoperation2 = $result6->fetch_assoc();
if ($rowoperation2['varid'] != "" AND $rowoperation2['varid'] != "0") {
$output2 = preg_replace("#\b\!(.*)\![A-Z]{1,3}\d+\b#", "var".$rowoperation2['varid']."", $output);
}
}
Can someone perhaps help?
Thank you,
Regards
Olaf
Why not using a simple preg_match instead of preg_match_all, you don't need word boundary and exclamation mark doesn't need to be escaped, the strings you're looking for are in group 1 and 2:
$str = '"!asksheet!H69=var8949"';
preg_match('#!(.*?)!([A-Z]{1,3}\d+)#', $str, $m);
print_r($m);
Output:
Array
(
[0] => !asksheet!H69
[1] => asksheet
[2] => H69
)

Parsing a string field

I have these Syslog messages:
N 4000000 PROD 15307 23:58:12.13 JOB78035 00000000 $HASP395 GGIVJS27 ENDED\r
NI0000000 PROD 15307 23:58:13.41 STC81508 00000200 $A J78036 /* CA-JOBTRAC JOB RELEASE */\r
I would like to parse these messages into various fields in a Hash, e.g.:
event['recordtype'] #=> "N"
event['routingcode'] #=> "4000000"
event['systemname'] #=> "PROD"
event['datetime'] #=> "15307 23:58:12.13"
event['jobid'] #=> "JOB78035"
event['flag'] #=> "00000000"
event['messageid'] #=> "$HASP395"
event['logmessage'] #=> "$HASP395 GGIVJS27 ENDED\r"
This is the code I have currently:
message = event["message"];
if message.to_s != "" then
if message[2] == " " then
array = message.split(%Q[ ]);
event[%q[recordtype]] = array[0];
event[%q[routingcode]] = array[1];
event[%q[systemname]] = array[2];
event[%q[datetime]] = array[3] + " " +array[4];
event[%q[jobid]] = message[38,8];
event[%q[flags]] = message[47,8];
event[%q[messageid]] = message[57,8];
event[%q[logmessage]] = message[56..-1];
else
array = message.split(%Q[ ]);
event[%q[recordtype]] = array[0][0,2];
event[%q[routingcode]] = array[0][2..-1];
event[%q[systemname]] = array[1];
event[%q[datetime]] = array[2] + " "+array[3];
event[%q[jobid]] = message[38,8];
event[%q[flags]] = message[47,8];
event[%q[messageid]] = message[57,8];
event[%q[logmessage]] = message[56..-1];
end
end
I'm looking to improve the above code. I think I could use a regular expression, but I don't know how to approach it.
You can't use split(' ') or a default split to process your fields because you are dealing with columnar data that has fields that have no whitespace between them, resulting in your array being off. Instead, you have to pick apart each record by columns.
There are many ways to do that but the simplest and probably fastest, is indexing into a string and grabbing n characters:
'foo'[0, 1] # => "f"
'foo'[1, 2] # => "oo"
The first means "starting at index 0 in the string, grab one character." The second means "starting at index 1 in the string, grab two characters."
Alternately, you could tell Ruby to extract by ranges:
'foo'[0 .. 0] # => "f"
'foo'[1 .. 2] # => "oo"
These are documented in the String class.
This makes writing code that's easily understood:
record_type = message[ 0 .. 1 ].rstrip
routing_code = message[ 2 .. 8 ]
system_name = message[ 10 .. 17 ]
Once you have your fields captured add them to a hash:
{
'recordtype' => record_type,
'routingcode' => routing_code,
'systemname' => system_name,
'datetime' => date_time,
'jobid' => job_id,
'flags' => flags,
'messageid' => message_id,
'logmessage' => log_message,
}
While you could use a regular expression there's not much gained using one, it's just another way of doing it. If you were picking data out of free-form text it'd be more useful, but in columnar data it tends to result in visual noise that makes maintenance more difficult. I'd recommend simply determining your columns then cutting the data you need based on those from each line.

Handling Multiline Cells in Ruby CSV

require 'csv'
input = CSV.read("test_first.csv", :encoding => 'ascii')[1 .. -1]
DOC = "test_final.csv"
profile = []
profile[0] = "Multiline"
profile[1] = "Standard"
CSV.open(DOC, mode = 'w', :force_quotes => true) do |me|
me << profile
end
a = 0
b = input.length
while a < b
temp = []
temp = input[a]
profile = []
profile[0] = ' A text string with embedded newlines
as well as some substitution from the source file: '"#{temp[0]}"''
profile[1] = temp[1]
CSV.open(DOC, mode = "a", :force_quotes => true ) do |me|
me << profile
end
a += 1
end
The resulting file test_final.csv retains the desired newlines within the cells however the force_quotes isn't working as expected and the embedded newlines aren't being escaped. So when the test_final.csv is reviewed in a text editor it has more lines than intended because each newline is being treated as a new row.
I tried appending the offending column with it's own unique row separator> profile[0] = ' A text string with embedded newlines
as well as some substitution from the source file: '"#{temp[0]}"'~' and assigning that in the options hash like so> :row_sep => "~" but this didn't seem to work.
Some clarification as to the desired input and output
Desired Input:
test_first.csv
1.testHeader1,testheader2
2.sub1,standard1
3.sub2,standard2
Desired Output:
test_final.csv
1.Multiline,Standard
2. A text string with embedded newlines
as well as some substitution from the source file: sub1,standard1
3. A text string with embedded newlines
as well as some substitution from the source file: sub2,standard2
What I'm getting right now instead is:
test_fail.csv
1.Multiline,Standard
2. A text string with embedded newlines
3. as well as some substitution from the source file: sub1,standard1
4. A text string with embedded newlines
5. as well as some substitution from the source file: sub2,standard2

preg_replace technicality in PHP regular expressions

My current code:
$text = "This is my string exec001 and this is the rest of the string exec222 and here is even more execSOMEWORD a very long string!";
$text2 = preg_replace('/\bexec(\S+)/', "<html>$1</html><div>$1</div>",, $text);
echo $text2,"\n";
Outputs the following:
This is my string <html>001</html><div>001</div> and this is the rest of the string <html>222</html><div>222</div> and here is even more <html>SOMEWORD</html><div>SOMEWORD</div> a very long string!
My question is, how can I store multiple variables? For example: I want to replace execVARIABLE1:VARIABLE2:VARIABLE3 and store each of VARIABLE1, 2 and 3 in say $1, $2 and $3 when the string is rewritten.
In order to save the matched groups you can use preg_match():
$text = "This is my string exec001 and this is the rest of the string exec222 and here is even more execSOMEWORD a very long string!";
preg_match( '/.*?\bexec(\S+).*?\bexec(\S+).*?\bexec(\S+)/', $text, $matches);
print_r($matches);
OUTPUT
Array
(
[0] => This is my string exec001 and this is the rest of the string exec222 and here is even more execSOMEWORD
[1] => 001
[2] => 222
[3] => SOMEWORD
)
Thanks to M42, we have the correct answer as follows:
$text2 = preg_replace('/\bexec([^:\s]+):([^:\s]+)/', "<html>$1</html><div>$2</div>", $text);

Resources