How can I pass in text rather than a file as a variable - perl

I want to pass text in as a variable rather than a file.
I am not sure how to explain this well only with an example.
I have a perl script with usage as follows printme.pl [file]
I want to run without passing in a file and just passing text.
echo print_me | perl printme.pl
rather than doing
perl printme.pl textfile.txt
I am trying to run a perl script that takes a text file as a variable and outputs using echo.

bash (amongst other shells) has a feature called process substitution. In this feature, you can add some shell code that outputs to stdout and have the shell treat it like a file.
In your case, you would write:
perl printme.pl <(echo "hello world")
Perl will receive in $ARGV[0] a filename that looks something like /dev/fd/63 from which it can read the line "hello world\n"

Related

way to fetch the argument inside perl script

I am having some trouble of getting the argument passed in in the following script
echo "abc"|perl <<'EOF'
#how to get "abc". it seems not $ARGV[0] nor in <STDIN>
EOF
Thank you.
The precise command line you have there may be your problem, if that is what you're actually executing. What you are saying there is "put 'abc' on the standard input of the next thing in the pipeline. Now run a Perl script consisting of a single comment."
This will do nothing, because there's nothing executable in that Perl script. Try this:
echo "abc" | perl -e 'print <STDIN>'
If you have a short Perl script the -e option is the way to go.
Your example is not using argument, it's using standard input. You can read standard input with the I/O operators. If you actually mean that you want an argument like myscript.pl --arg then I would recommend using Getopt::Long.
You have not passed any argument to the Perl script.
You redirected the Perl script itself so it comes from standard input; that means that the piped output goes nowhere and cannot be seen by Perl.
Reconsider how you're invoking your script. Maybe:
perl script.pl "abc"
where script.pl is a file that contains the Perl script you used as a here-document. Or simply make that script executable (perhaps without the .pl suffix).
Your problem is that both the pipe and the here-document redirect the STDIN. And the here-document wins, so the perl process never sees the pipe; it gets the script on STDIN (and has read to EOF before running the script, so that will see STDIN at EOF).
Observe:
$ echo "abc" | perl <<'EOF'
print "[What have we here?]\n";
seek(STDIN, 0, 0);
print <STDIN>;
print "[Well, what do you know ...]\n";
EOF
[What have we here?]
print "[What have we here?]\n";
seek(STDIN, 0, 0);
print <STDIN>;
print "[Well, what do you know ...]\n";
[Well, what do you know ...]
$
Moral: Don't try to mix pipes and here-documents in the shell. :)

Run Perl Script From Unix Shell Script

Hi I have a Unix Shell Script call Food.sh ; I have a Perl Script call Track.pl. Is there a way where I can put Track.pl's code in to Food.sh code and still have it work ? Track.pl requires one arugement to label a name of a folder.
Basically it will run like this.
Unix Shell Script codes RUN
step into
Perl Script codes RUN
Put in name of folder for Perl script
Rest of script runs
exit out.
You have a few options.
You can pass the code to Perl using -e/-E.
...
perl -e'
print "Hello, World!\n";
'
...
Con: Escaping can be a pain.[1]
You can pass the code via STDIN.
...
perl <<'END_OF_PERL'
print "Hello, World!\n";
END_OF_PERL
...
Con: The script can't use STDIN.
You can create a virtual file.
...
perl <(
cat <<'END_OF_PERL'
print "Hello, World!\n";
END_OF_PERL
)
...
Con: Wordy.
You can take advantage of perl's -x option.
...
perl -x -- "$0"
...
exit
#!perl
print "Hello, World!\n";
Con: Can only have one snippet.
$0 is the path to the shell script being executed. It's passed to perl as the program to run. The -x tells Perl to start executing at the #!perl line rather than the first line.
Ref: perlrun
Instances of ' in the program needs to escaped using '\''.
You could also rewrite the program to avoid using '. For example, you could use double-quoted string literals instead of single-quoted string literals. Or replace the delimiter of single-quoted string literals (e.g. q{...} instead of '...'). As for single-quoted inside of double-quoted and regex literals, these can be replaced with \x27, which you might find nicer than '\''.
(I'm assuming your goal is just to have all of the code in a single file so that you don't have multiple files to install)
Sure, there's a way to do this, but it's cumbersome. You might want to consider converting the shell script entirely to Perl (or the Perl script entirely to shell).
So ... A way to do this might be:
#!/bin/sh
echo "shell"
perl -E '
say "perl with arg=$ARGV[0]"
' fred
echo "shell again"
Of course, you'd have to be careful with your quotes within the Perl part of the program.
You might also be able to use a heredoc for the Perl part to avoid quoting issues, but I'm not sure about that.

Inserting headers into multiple files

I found some command line with Perl that inserts headers into my files without going through the tedious process of inserting them one by one. Can someone walk me through the Perl aspect of this command line? I'm new to this and can't seem to find the right explanations for what I wrote.
cat header.txt | perl -0 -i -pe 'BEGIN{$h = <STDIN>}; print $h' 1*
-e
rather than provide a script in a xxxx.pl file, provide it on the command line
-p
makes it iterate over filename arguments somewhat like sed but also prints the contents of $_ at the end of the script.
the two above are combined in -pe
-i
indicate you want to edit the file in place and write the output to the same file. In practice, Perl renames the input file and reads from this renamed version while writing to a new file with the original name
-0
redefines the end of record character (\n by default) so that you can read the entire input file as a single line
1*
is the command line argument to your script, so I guess you are modifying any file with a name that starts with 1 (you could have used *.c, or whatever depending on the type of files you are trying to modify)
print $h
prints the variable $h that is the "main" of your script. if it was initialized with the content of the header file (the intent of this one-liner) then it will print the header file
BEGIN{ some code here }
this is stuff you execute before the script starts. this is where I'm stumped. this doesn't seem like valid perl code
so basically:
this will supposedly slurp the entire header file (because of -0) in the BEGIN block and store it in the variable $h
iterate over all the files specified by the wildcards at the end of the command line
for each file: print the header (print $h) then print hte file itself (because of -pe)
so it's equivalent to spelling the script out:
$h = gets content of the entire header file
while (<>){ #loop implied by -pe, iterates over all the 1* files
# the main contents of the "-e" script are inserted below as part of executing -pe
print h$; #print the header we saved
print $_; # implied by -pe, and since we are using -0, this prints the entire content in one shot
# end of the "-e" script. again it was a single print $h statement, the second print is implied by -pe
}
It's a bit hard to explain, take a look at the perlrun documentation for details (run man perlrun).
This is not 100% complete explanation because I don;t think the BEGIN block is right. I tried it on my ubuntu machine and it complained about its syntax too
Here's something similar, with an explanation. The program in the question doesn't run on my mac.
I needed to add the #nullable disable directive to the top of all my csharp files as part of migrating to nullable reference types.
perl -w -i -p -0777 -e 's/^/#nullable disable\n\n/' $(find . -iname '*.cs')
-w enable warnings
-i edit files in place
-p read each file block by block, printing each block after applying a perl expression. the default block size is one line
-0777 changes the default block size to the entire file
-e the perl expression to execute
The final argument uses shell command substitution to create a list of files. It passes that list of file paths to the perl command. The find command searches for files that end in .cs.
The perl program is a single substitution command. It matches the very beginning of the block and replaces (prepends, really) with "#nullable disable" and a couple new-lines.

Executing perl code inside shell script using eval

I came across the following example. I tried to google but could not find much so I'm posting this question here.
What is the benefit of executing the perl script like this?
How can we make the shell script work like a "normal" shell script once we are through executing the perl code?
Here's the code:
#!/bin/ksh
#! -*- perl -*-
eval 'exec $PERLLOCATION/bin/perl -x $0 ${1+"$#"} ;'
if 0;
print "hello world\n";
# how can I make it behave like a "normal" shell script from this point onwards? What needs to be done?
# echo "hello world" ### this results in error
This idiom is described in the perlrun documentation.
The -x switch scans the whole file and ignores anything that appears before the first line that begins with #! and also contains the word perl.
It means that your system will run the script with the Perl interpreter whether you invoke the script with perl or with a shell command (sh/bash/ksh/etc.)
That is,
$ perl this_script
and
$ sh this_script
will both run the script with perl.
To address your second question, this idiom has just about nothing to do with combining shell script and Perl script in the same file. There are a few different ways to approach that problem, but maybe the most readable way is to write in shell script, but use the shell's heredoc notation to invoke perl code.
#!/bin/bash
# this is a bash script, but there is some Perl in here too
echo this line is printed from the shell
echo now let\'s run some Perl
perl <<EOF
# this is now perl script until we get to the EOF
print "This line is printed from Perl\n";
EOF
echo now this is from the shell script again
1. If you start a Perl script in the usual way:
#!/usr/bin/perl
print "hello world\n";
the #! line will only work if the Perl interpreter is actually installed under /usr/bin. The perl/ksh bilingual script you show is a tricky kluge to make the script work even if perl is installed somewhere else. For more information, see e.g. this.
2. You can't. When the shell process encounters the exec command, it terminates and hands control over to perl. (Technically, it executes perl in place of the shell, without creating a new process.) The only way to run more shell commands after that would be to launch a new shell.
It's way simpler than what's already been posted.
#!$PERLLOCATION/bin/perl
doesn't work because the shebang (#!) line is interpreted by the kernel (not the shell), and the kernel doesn't do variable interpolation.
The code invokes ksh to expand the environment variable and to launch the specified installation of Perl.

How can I call a Perl function from a shell script?

I have written a library in Perl that contains a certain function, that returns information about a server as a character string. Can I call this function from a shell directly?
My boss asks "Can you call it from a shell directly for the time being?" Because he said that, I think I should be able to do it, but how do I do it?
perl -MServerlib=server_information -e 'print server_information()'
Is another way to do this, but only if Serverlib exports server_information sub. If it doesn't, you would need to do the below instead:
perl -MServerlib -e 'print MServerlib::server_information()'
As perl's command line arguments are a bit inscrutable, I'd wrap it in a simpler perl script that calls the function. For example, create a script serverinfo which contains:
#!/usr/bin/perl
require 'library.pl';
say library::getServerInformation();
then run:
chmod u+x serverinfo
The advantage of doing it this way is the output and arguments of the script can be corrected if the function itself changes. A command line script like this can be thought of as an API, which shouldn't change when the implementation changes.