Why does this command for qsub to submit multiple pbs scripts work in the bash shell but not fish? - hpc

I have a bunch of .pbs files in one directory.
I can qsub the files no problem with this command in the bash shell but for the fish shell, I continuously hit enter and it just creates a new input line. Any ideas why it doesn't work in fish?
for file in *.pbs; do qsub $file; done

Fish's syntax for loops and other block constructs is different.
In this case it's
for file in *.pbs
qsub $file
end
or, on one line:
for file in *.pbs; qsub $file; end
Other looping constructs look similar - no introductory "do" and they end with "end".
Other differences here: This behaves like bash with the nullglob option, so if no file matches the for-loop simply won't be executed, there's no need to guard for a literal *.pbs being passed.
Also the $file doesn't need to be quoted because it's set as one element and so it will be passed as one element, no word splitting takes place.
Fish uses a different script syntax from bash and other shells. To read up on it: Fish for bash users is the quick starting point, but the rest of the documentation is worth reading (in my, admittedly biased, opinion).

Related

What is the purpose of filtering a log file using this Perl one-liner before displaying it in the terminal?

I came across this script which was not written by me, but because of an issue I need to know what it does.
What is the purpose of filtering the log file using this Perl one-liner?
cat log.txt | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)/ /g'
The log.txt file contains the output of a series of commands. I do not understand what is being filtered here, and why it might be useful.
It looks like the code should remove ANSI escape codes from the input, i.e codes to set colors, window title .... Since some of these code might cause harm it might be a security measure in case some kind of attack was able to include such escape codes into the log file. Since usually a log file does not contain any such escape codes this would also explain why you don't see any effect of this statement for normal log files.
For more information about this kind of attack see A Blast From the Past: Executing Code in Terminal Emulators via Escape Sequences.
BTW, while your question looks bad on the first view it is actually not. But you might try to improve questions by at least formatting it properly. Otherwise you risk that this questions gets down-voted fast.
First, the command line suffers from a useless use of cat. perl is fully capable of reading from a file name on the command line.
So,
$ perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)/ /g' log.txt
would have done the same thing, but avoided spawning an extra process.
Now, -e is followed by a script for perl to execute. In this case, we have a single global substitution.
\e in a Perl regex pattern corresponds to the escape character, x1b.
The pattern following \e looks like the author wants to match ANSI escape sequences.
The -p option essentially wraps the script specified with -e in while loop, so the s/// is executed for each line of the input.
The pattern probably does the job for this simple purpose, but one might benefit from using Regexp::Common::ANSIescape as in:
$ perl -MRegexp::Common::ANSIescape=ANSIescape,no_defaults -pe 's/$RE{ANSIescape}/ /g' log.txt
Of course, if one uses a script like this very often, one might want to either use an alias, or even write a very short script that does this, as in:
#!/usr/bin/env perl
use strict;
use Regexp::Common 'ANSIescape', 'no_defaults';
while (<>) {
s/$RE{ANSIescape}/ /g;
print;
}

The perl -pe command

So I've done a research about the perl -pe command and I know that it takes records from a file and creates an output out of it in a form of another file. Now I'm a bit confused as to how this line of command works since it's a little modified so I can't really figure out what exactly is the role of perl pe in it. Here's the command:
cd /usr/kplushome/entities/Standalone/config/webaccess/WebaccessServer/etc
(PATH=/usr/ucb:$PATH; ./checkall.sh;) | perl -pe "s,^, ,g;"
Any idea how it works here?
What's even more confusing in the above statement is this part : "s,^, ,g;"
Any help would be much appreciated. Let me know if you guys need more info. Thank you!
It simply takes an expression given by the -e flag (in this case, s,^, ,g) and performs it on every line of the input, printing the modified line (i.e. the result of the expression) to the output.
The expression itself is something called a regular expression (or "regexp" or "regex") and is a field of learning in and of itself. Quick googles for "regular expression tutorial" and "getting started with regular expressions" turn up tons of results, so that might be a good place to start.
This expression, s,^, ,g, adds ten spaces to the start of the line, and as I said earlier, perl -p applies it to every line.
"s,^, ,g;"
s is use for substitution. syntax is s/somestring/replacement/.
In your command , is the delimiter instead of /.
g is for work globally, means replace all occurrence.
For example:
perl -p -i -e "s/oldstring/newstring/g" file.txt;
In file.txt all oldstring will replace with newstring.
i is for inplace file editing.
See these doc for information:
perlre
perlretut
perlop

Is it possible to pipe input to another script with '<' using the system() in perl?

I've looked at several similar questions but none of them seem to address this issue, or they use a form of piping that I'm unfamiliar with, or I'm using "piping" in place of the correct word.
First, I'm on windows 7 and what I'm trying to do is get a Perl script to call and input to another Perl Script multiple times.
The way I'm going about doing this is with the System() function.
When put directly into the command line this works, although a little sloppy:
Functionalscript.pl < InputFile > OutputFile
That takes stuff from the input file performs the function and writes it to the output file flawlessly. However, when using the "system()" function in my calling script the input is not registered, but the output file is created (it's just blank).
The problem is with:
system("Functionalscript.pl < InputFile > OutputFile")
For some reason when that is used the functionalscript does not receive the input as stdin. Is there a way to make this work?
According to perldoc -f system (http://perldoc.perl.org/functions/system.html):
If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp , which is more efficient.
Which means if your command has > or < in it it should be passed to the shell, and the input and output redirection should work as expected.
system("x:/path/perl.exe Functionalscript.pl InputFile > OutputFile")
Supplied by mpapec, Works. The "x:/path/perl.exe" had to be included.

cshell: running cat on a large text file inside backticks gives 'word too long'

I have a file that has fairly long lines. The longest line has length 4609:
% perl -nle 'print length' ~/very_large_file | sort -nu | tail -1
4609
Now, when I just run cat ~/very_large_file it runs fine. But when I put inside backticks, it gives a 'word too long' error
% foreach line (`cat ~/very_large_file`)
Word too long.
% set x = `cat ~/very_large_file`
Word too long.
Is there an alternative to using backticks in csh to process each line of such a file?
Update My problem was solved by using a different language, but I still couldn't get the reason for the failing csh. Just came across this page that describes the manner of finding ARG_MAX. In particular, the getconf command is useful. Of course, I am still not sure whether this limit is the root cause, and if the limit applies to the languages other than csh.
I don't mean to beat an old horse, but if you're scripting do consider moving to bash, zsh or even Korn. csh has disadvantages.
What you can try without abandoning csh completely:
Move to tcsh if you're with regular old (very old) csh.
Recompile tcsh with a longer word length (the default is 1000 bytes, I think) or with dynamic allocation.
If possible move the line processing to a secondary script or program and write that loop like this:
cat ~/very_large_file | xargs secondary_script

Calling perl script from a perl script

I want to call a perl script from a perl script with big argument list in a bash shell. The arguments contains special characters such as \, *, (, ) etc. Each of these special characters are guided by single escape character \.
But when I call 2nd perl script (which then calls to a shell script) from 1st perl script the escape character gets evaluated and the special characters are exposed in the shell and hence getting syntax error.
So basically i want to prevent escape character's evaluation when I call 2nd perl script from 1st perl script and it should be evaluated when I call shell script from my 2nd perl script.
Eg. Input to the first perl 'MonitorAdmin' script is :
MonitorAdmin -reversefilter -container="LogServerContainer" -filepath="/home/esg2/YogeshTemp/VSDEFAULT/logs" -filename="System.log" -pattern=".*\t.*\t(DEBUG)\t.*\t.*\t.*\t(SecurityService)\t.*\t.*\t.*\t.*\t.*" -linecount="5001" -targetfile="
Perl's exec and system commands won't invoke a shell if you pass them a list with more than one element, but each list element becomes a separate argument then, i.e. spaces don't separate arguments. I'd imagine this works well even when executing a shell script since you aren't invoking the shall with a -c option.
There are two forms of system, one that executes a shell command (system($shell_cmd)), and one that launches a program (system($program, #args)). As best as we can tell by your light post, you appear to be using the wrong one. All you need is
system('MonitorAdmin2', #ARGV)
There is no shell to "misinterpret" the characters.

Categories