In Scala, read a file where specified path includes multiple environment variables - file

For a file path name such as
val path = "$HOME/projects/$P1/myFile.txt"
is there a simpler way to resolve the path and read myFile.txt than this,
import java.io.File
val resolvedPath = path.split(File.separator).map{ s =>
if (s.startsWith("$")) sys.env(s.drop(1))
else s }.
mkString(File.separator)
val res = io.Source.fromFile(resolvedPath).getLines

The way you have seems good to me, but if you are so inclined or need to do something quickly, you could use Process to get the return of executing a bash command:
import scala.sys.process._
val cleanedPath = Seq("bash", "-c", "echo " + path).!!.trim
You can even use this idea to read the file if you want:
val text = Seq("echo", "-c", "cat " + path).!!
One difference between these and your code is that your code will throw an exception if an environment variable is missing, while bash returns an empty string for that variable. If you wish to mimic that, you could use sys.env.get(s.tail).getOrElse("") instead of sys.env(s.drop(1)) or use the dictionary val myEnv = sys.env.withDefaultValue("").

See System.getenv(). You'll be able to find the variables and replace them with the value to resolve your path.

Related

Create text file to write/add of a couple of images name

I tried to get a script to create a text file that could write/add the images name, but the function
FileID = CreateFileForWriting(filename) does not work, it shows that was used by other process
I did not get this, is this function not right format or something is wrong, thx
Number Totaln
totaln=countdocumentwindowsoftype(5)
String filename, text
Number fileID
if (!SaveasDialog( "save text file as",getapplicationdirectory(2,0) + "Imagename.txt", filename))exit(0)
fileID = CreateFileForWriting(filename)
number i
for(i = 0; i <totaln; i++)
{
image imgSRC
imgSRC := GetFrontImage()
string imgname=getname(imgSRC)
WriteFile(fileID,"imgname")
Result("imgname")
}
Your code is nearly fine, but if you use the low-level API for file I/O you need to ensure that you close files you've opened or created.
Your script doesn't. Therefore, it runs fine exactly 1 time but will fail on re-run (when the file is still considered open.)
To fix it, you need to have closefile(fileID) at the end.
( BTW, if you script exits or throws after opening a file but before closing it, you have the same problem. )
However, I would strongly recommend not using the low-level API but the file streaming object instead. It also provides an automated file-closing mechanism so that you don't run into this issue.
Doing what you do in your script would be written as:
void writeCurrentImageNamesToText()
{
number nDoc = CountImageDocuments()
string filename
if (!SaveasDialog( "save text file as",getapplicationdirectory(2,0) + "Imagename.txt", filename)) return
number fileID = CreateFileForWriting(filename)
object fStream = NewStreamFromFileReference(fileID,1) // 1 for auto-close file when out of scope
for( number i = 0; i <nDoc; i++ ){
string name = GetImageDocument(i).ImageDocumentGetName()
fStream.StreamWriteAsText( 0, name + "\n" ) // 0 = use system encoding for text
}
}
writeCurrentImageNamesToText()

Angular path with hyphen character not allowed

When I use the following:
$location.path('/product/ninja-game'); //No error in console but the path isn't changed
The path is not changed but it works when I use following:
$location.path('/product/ninja_game');
Is there anything specific to hyphen/dash character in angularjs path. I couldn't find anything specific in the docs.
Code:
$scope.buildProductDetails = function(product) {
var tempTitle = product.title.toLowerCase();
tempTitle = tempTitle.replace(/adobe/g, "").trim();
tempTitle = tempTitle.replace(/\s+/g, '-'); //replacing space with hyphen
console.log(tempTitle);
$location.path('/product/' + tempTitle);
}
Hyphen/dash should not be a problem
Probably the problem is in the variable tempTitle.
Hardcode the path like $location.path('/product/ninja-game'); and check just to see whether the problem in the variable tempTitle.

How to make a search in filesystem-like structure in Haskell

problem
I have a Type:
data FSObject = Folder String [FSObject] | File String
and I need to make a function
search :: String -> FSObject -> Maybe String
that returns a path to File that we are searching for (if exists)
(String in search function should be equal to the name (the String in File object (w/o path)) of the searched File.
my thoughts/tryings
I feel like I am not doing it properly- in a functional way. I am new to this language so I am sorry for the following code.
I was trying to do this for several hours. I was trying like this:
heler function contains that returns true if given FSObject contains File that we are looking for
helper function that returns first element with the File (using previous function and "find" function)
helper function to deal with conversion from Maybe String to String
My search function would check if there is the File, if no-> return Nothing, else return Just with String computed somehow using recursion
I can paste my work but I don't know how to make it work, its totally unreadable etc.
Do some1 has hints/comments to share? How to properly deal with Maybe in this kind of problems?
You can do this using recursion.
findPath::String->FSObject->Maybe String
findPath name (File name') | name == name' = Just name
findPath _ (File _) = Nothing
findPath name (Folder path contents) =
fmap ((path ++ "/") ++) $ msum $ map (findPath name) contents
The only tricky point is the last part. Breaking the last line apart....
map (findPath name) contents
will output a list of subresults
[Just "a/b/filename", Nothing, Just "c/d/filename", ....]
msum will take the first Just in the list, throwing the rest away (and, by laziness, nothing further than that first value will actually be created)
Finally, the path is prepended (the fmap is there to reach inside the Maybe)
While #jamshidh solution is short, it isn't modular and the final result. Here is my process of writing the program. Two main points:
I'll use so called "generate then search" approach: first I generate paths for all files, then I search the collection for the right path
I'll store path as list of components - this way the code will be more generic (in Haskell more generic code is less error-prone) and I will insert path separators afterwards in a small function (so I can do one thing at a time which is easier).
Ok I need function allPaths that gives me list of all files along with their paths. All paths of a single file is that single file, and all paths of a folder is concatenated collections of paths from children with prepended folder name:
allPaths (File file) = singleFile file
allPaths (Folder folder children) = concatMap (addFolder folder . allPaths) children
I actually wrote the code top-down. So I didn't bother defining singleFile and addFolder at this point. Single file is simple:
singleFile file = [(file, [])]
addFolder adds f to second component of a tuple. There is a function in Control.Arrow for that already, but I add its implementation here for simplicity:
second f (a,x) = (a, f x)
addFolder f files = map (second (f:)) files
When I was learning Haskell it was hard to write such code at once, but now it's automatic and without intermediate steps.
Now we basically implement search by filtering all matching files, taking the first match and extracting the path. Oh, there is already function lookup in the standard library for that:
search fileToSearch l = lookup fileToSearch $ allPaths l
It took me quite a while to figure out how to compose lookup and allPaths. Fortunately the order in the tuple was chosen correctly by accident.
Note that you still need to convert folder list to a path by inserting separators and appending filename as necessary using concatMap.
You should create a recursive function using an accumulation parameter to save the current path where you're searching. It would be something like this:
search str (File f) = if str == f then Just str else Nothing
search str (Directory dir (x:xs)) =
Just (sear str [] (Directory dir (x:xs))) where
sear str path (File f) = if str == f then (path ++ "/" ++ str ++ "|") else []
sear str path (Directory y []) = []
sear str path (Directory dir (x:xs)) = sear str (path ++ "/" ++ dir) x ++ sear str path (Directory dir xs)
I hope it's helpful for you.

Put contents of a file in a variable

I have put some values in a file. In the puppet manifests I want to get the value of these variables. Is there a specific directory to put my file? Also, what should be the format of the file?
If this file on puppet-server, you can write functions for module. For example:
modules/my_module/lib/puppet/parser/functions/get_var.rb:
$: << File.expand_path(File.join(File.dirname(__FILE__), '.'))
module Puppet::Parser::Functions
newfunction(:get_var,
:type => :rvalue) do |args|
file_name = args[0]
f = File.open(file_name)
s = f.readline()
return s
end
end
And use it in manifests: $test = get_var('/etc/puppet/configs.txt'). This function return first string from file, but you can change it for your needs.
For file on client, you can write facter.

Perl IO::Pipe does not work within arrays

im trying the following:
I want to fork multiple processes and use multiple pipes (child -> parent) simultaneously.
My approach is to use IO::Pipe.
#!/usr/bin/perl
use strict;
use IO::Pipe;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my #ua_processes = (0..9);
my $url = "http://<some-sample-textfile>";
my #ua_pipe;
my #ua_process;
$ua_pipe[0] = IO::Pipe->new();
$ua_process[0] = fork();
if( $ua_process[0] == 0 ) {
my $response = $ua->get($url);
$ua_pipe[0]->writer();
print $ua_pipe[0] $response->decoded_content;
exit 0;
}
$ua_pipe[0]->reader();
while (<$ua_pipe[0]>) {
print $_;
}
In future i want to use multiple "$ua_process"s in an array.
After execution i got the following errors:
Scalar found where operator expected at ./forked.pl line 18, near "] $response"
(Missing operator before $response?)
syntax error at ./forked.pl line 18, near "] $response"
BEGIN not safe after errors--compilation aborted at ./forked.pl line 23.
If i dont use arrays, the same code works perfectly. It seems only the $ua_pipe[0] dont work as expected (together with a array).
I really dont know why. Anyone knows a solution? Help would be very appreciated!
Your problem is here:
print $ua_pipe[0] $response->decoded_content;
The print and say builtins use the indirect syntax to specify the file handle. This allows only for a single scalar variable or a bareword:
print STDOUT "foo";
or
print $file "foo";
If you want to specify the file handle via a more complex expression, you have to enclose that expression in curlies; this is called a dative block:
print { $ua_pipe[0] } $response-decoded_content;
This should now work fine.
Edit
I overlooked the <$ua_pipe[0]>. The readline operator <> also doubles as the glob operator (i.e. does shell expansion for patterns like *.txt). Here, the same rules as for say and print apply: It'll only use the file handle if it is a bareword or a simple scalar variable. Otherwise, it will be interpreted as a glob pattern (implying stringification of the argument). To disambiguate:
For the readline <>, we have to resort to the readline builtin:
while (readline $ua_pipe[0]) { ... }
To force globbing <>, pass it a string: <"some*.pattern">, or preferably use the glob builtin.

Resources