Replacing part of the content in one file with data from another file - ruby

I have an html file myfile.html, which includes a script with a line like this:
var json = '[{"name":"Hydrogen","number":"1","symbol":"H","weight":"1.00794"},{"name":"Helium","number":2,"symbol":"He","weight":4.002602},{"name":"Lithium","number":3,"symbol":"Li","weight":6.941},{"name":"Beryllium","number":4,"symbol":"Be","weight":9.012182},{"name":"Boron","number":5,"symbol":"B","weight":10.811},{"name":"Carbon","number":6,"symbol":"C","weight":12.0107}]';
The string within single quotes that is assigned to variable json will actually vary. I would like to replace this string with the entire contents of another file myjson.json.
I tried with the code here:
Find and replace in a file in Ruby
and here:
search and replace with ruby regex
doing this:
replace = File.read("myjson.json")
changefile = File.read("myfile.html")
changefile.sub( %r{var json = '[^<]+';}, replace )
but its not working. I'm not sure if its the regex I'm doing incorrectly, or if its something more.
UPDATE
After reading the reply below, my first attempt was:
replace = File.read("myjson.json")
changefile = File.read("myfile.html")
changefile.sub!(%r{var json = '.+'}, replace)
puts changefile
This did the find correctly, but removed all of the var json = '' and replaced it with myjson.json - I want to keep var json = and only replace the contents between the two single quotes after. So then I tried:
replace = File.read("myjson.json")
changefile = File.read("myfile.html")
changefile.sub!(%r{var json = '.+'}, "var json = 'replace'")
puts changefile
But that just replaced it with var json = 'replace'
I want to use the original var json = to find the location, but I don't want it to be removed.
So I did something I know is dumb and wrong, but it worked:
replace = File.read("myjson.json")
changefile = File.read("myfile.html")
changefile.sub!(%r{var json = '.+'}, "var json = 'thanksforthehelptinman'")
changefile.sub!(%r{thanksforthehelptinman}, replace)
puts changefile
Thanks for the help!

The regex isn't right because [ and ] are reserved in regex. You need to escape them:
%r{var json = '\[.+\]'}
I can't be more exact because I don't know what's in your JSON file, but that should get you into the ballpark.
Also, unless you assign changefile.sub to something, the substitution will be thrown away. You can do one of these two things:
changefile = changefile.sub(%r{var json = '\[.+\]'}, json)
or mutate changefile:
changefile.sub!(%r{var json = '\[.+\]'}, json)

Related

Is there a way to read fixed length files using csv.reader() module in Python 2.x

I have a fixed length file like:
0001ABC,DEF1234
The file definition is:
id[1:4]
name[5:11]
phone[12:15]
I need to load this data into a table. I tried to use CSV module and defined the fixed lengths of each field. It is working fine except for the name field.
For the NAME field, only the value till ABC is getting loaded. The reason is:
As I am using CSV module, it is treating 0001ABC, as a value and only parsing till that.
I tried to use escapechar = ',' while reading the file, but it removes the ',' from the data. I also tried quoting=csv.QUOTE_ALL but that didnt work either.
with open("xyz.csv") as csvfile:
readCSV = csv.reader(csvfile)
writeCSV = open("sample_csv", 'w');
output = csv.writer(writeCSV, dialect='excel', lineterminator="\n")
for row in readCSV:
print(row) # to debug #
data= str(row[0])
print(data) # to debug #
id = data[0:4]
name = data[5:11]
phone = data[12:15]
output.writerow([id,name,phone])
writeCSV.close()
Output of the print commands:
row: ['0001ABC','DEF1234']
data: 0001ABC
Ideally, I expect to see the entire set 0001ABC,DEF1234 in the variable: data.
I can then use the parsing as mentioned in the code to break it into different fields.
Can you please let me know where I am going wrong?

Ruby String to access an object attribute

I have a text file (objects.txt) which contains Objects and its attributes.
The content of the file is something like:
Object.attribute = "data"
On a different file, I am Loading the objects.txt file and if I type:
puts object.attribute it prints out data
The issue comes when I am trying to access the object and/or the attribute with a string. What I am doing is:
var = "object" + "." + "access"
puts var
It prints out object.access and not the content of it "data".
I have already tried with instance_variable_get and it works, but I have to modify the object.txt and append an # at the beginning to make it an instance variable, but I cannot do this, because I am not the owner of the object.txt file.
As a workaround I can parse the object.txt file and get the data that I need but I don't want to do this, as I want take advantage of what is already there.
Any suggestions?
Yes, puts is correctly spitting out "object.access" because you are creating that string exactly.
In order to evaluate a string as if it were ruby code, you need to use eval()
eg:
var = "object" + "." + "access"
puts eval(var)
=> "data"
Be aware that doing this is quite dangerous if you are evaluating anything that potentially comes from another user.

Use embedded string as variable name

I have a YAML file that uses the encoding __firstname__ as a placeholder which signifies that an existing method firstname should be used, rather than the literal string in a subsequent process.
I am trying to understand the most ruby way to to do this. Basically, I need to extract the part between the underscores and send it to an object. Here is pseudocode:
variable = '__firstname__'
if variable is prefixed and suffixed with underscores
result = object.send(variable.removeunderscores)
else
result = variable
end
puts result
I was about to write this procedurally like this, but this is the type of thing that I think ruby can less clunkily if only I knew the language better.
What is a clean why to write this?
There's nothing wrong with verbose code if it's clear to read IMO.
I'd do something like this using String#start_with? and String#end_with?:
variable = '__firstname__'
if variable.start_with?("__") && variable.end_with?("__")
result = object.send(variable[2...-2])
else
result = variable
end

After performing string.slice() return string with part removed

Im sure this is very obvious but I cant seem to get it work.
I have a Pathname instance and Im attempting to remove the first directory from it and then return the rest of the string, but because slice returns the part removed it seems there is no way of getting the smaller string back.
filepath = Pathname.new("this_folder_needs_to_go/another_folder/file.html")
filedir = filepath.to_s.slice("this_folder_needs_to_go/")
newfilepath = filedir
I would hope newfilepath would be another_folder/file.html but instead it just returns this_folder_needs_to_go/
So how on earth to I get the string that has had the part removed?
Using String#split:
"this_folder_needs_to_go/another_folder/file.html".split('/', 2)[1]
# => "another_folder/file.html"
You can also use .slice! instead of .slice if you're trying to modify your string
filepath = Pathname.new("this_folder_needs_to_go/another_folder/file.html")
filepath.to_s.slice!("this_folder_needs_to_go/")
puts filepath ==> "another_folder/file.html"
Though that will affect your filepath variable irreversibly.
#partition will also work in a similar manner to #split
filepath = Pathname.new("this_folder_needs_to_go/another_folder/file.html")
file_dir = filepath.partition("this_folder_needs_to_go/")[-1]
file_dir
#=> "another_folder/file.html"
#partition returns [head,sep,tail] so this will look like ["","this_folder_needs_to_go","/another_folder/file.html"] the [-1] says get the last element.

Iterate over Umbraco getAllTagsInGroup result

I'm trying to get a list of tags from a particular tag group in Umbraco (v4.0.2.1) using the following code:
var tags = umbraco.editorControls.tags.library.getAllTagsInGroup("document downloads");
What I want to do is just output a list of those tags. However, if I output the variable 'tags' it just outputs a list of all tags in a string. I want to split each tag onto a new line.
When I check the datatype of the 'tags' variable:
string tagType = tags.GetType().ToString();
...it outputs MS.Internal.Xml.XPath.XPathSelectionIterator.
So question is, how do I get the individual tags out of the 'tags' variable? How do I work with a variable of this data type? I can find examples of how to do it by loading an actual XML file, but I don't have an actual XML file - just the 'tags' variable to work with.
Thanks very much for any help!
EDIT1: I guess what I'm asking is, how do I loop through the nodes returned by an XPathSelectionIterator data type?
EDIT2: I've found this code, which almost does what I need:
XPathDocument document = new XPathDocument("file.xml");
XPathNavigator navigator = document.CreateNavigator();
XPathNodeIterator nodes = navigator.Select("/tags/tag");
nodes.MoveNext();
XPathNavigator nodesNavigator = nodes.Current;
XPathNodeIterator nodesText = nodesNavigator.SelectDescendants(XPathNodeType.Text, false);
while (nodesText.MoveNext())
debugString += nodesText.Current.Value.ToString();
...but it expects the URL of an actual XML file to load into the first line. My XML file is essentially the 'tags' variable, not an actual XML file. So when I replace:
XPathDocument document = new XPathDocument("file.xml");
...with:
XPathDocument document = new XPathDocument(tags);
...it just errors.
Since it is an Iterator, I would suggest you iterate it. ;-)
var tags = umbraco.editorControls.tags.library.getAllTagsInGroup("document downloads");
foreach (XPathNavigator tag in tags) {
// handle current tag
}
I think this does the trick a little better.
The problem is that getAllTagsInGroup returns the container for all tags, you need to get its children.
foreach( var tag in umbraco.editorControls.tags.library.getAllTagsInGroup("category").Current.Select("/tags/tag") )
{
/// Your Code
}

Resources