How do I convert csh aliases into MODULEFILE compatible set-alias commands? - module

I have a bunch of aliases that I would like to share with co-workers and I would like to put it in our project modulefile. Is there a script that would do the conversion for me? Or at least give me a good start and then I could fix the ones that didn't translate well?
P.S. Could someone with more rep create a modulefile tag?

I don't know of any tool that does the translation, but you can use something like this if the aliases are all one-liners:
Firstly, make a Tcl script like this, e.g., called convertalias.tcl:
while {[gets stdin line] >= 0} {
if {[regexp {^alias (\w+)='(.*)'$} -> name def]} {
puts [list set-alias $name $def]
} else {
puts stderr "Rejected line: $line"
}
}
Then use it in a bash command line like this (where bash$ is the prompt):
bash$ alias | tclsh convertalias.tcl >aliases.def
You'll then have to hack the aliases.def file, but it should give you a start. It will also print out any lines it couldn't grok (after all, it's just a stupid script...)

Related

Sharing variables between C Shell and TCL

I have a variable which is being used in two separate scripts: a C Shell one and a TCL one. Is there a way to define it just once and access it in both the scripts?
vars.sh
#!/usr/bin/env tcsh
set a=b
run.sh
#!/usr/bin/env tcsh
source vars.sh
echo $a
vars.tcl
#!/usr/bin/env tclsh
set a b
run.tcl
#!/usr/bin/env tclsh
source vars.tcl
puts $a
I do not like to idea of generating two separate files to store the same variables in two different formats. Is there a way to use a single vars file and have the variables available to both C Shell and TCL?
The simplest method is to make the variables be environment variables, since those are inherited by a child process from their parent. (On the Tcl side, they're elements in the ::env global array, and on the C shell side, they can be read like any other variable but need to be set via setenv.)
Sharing a single configuration file is much harder, since the two languages use a different syntax. Provided you don't use anything complicated in the way of quoting, you can make Tcl parse the C shell format.
proc loadVariablesFromCshellFile {filename arrayName} {
upvar 1 $arrayName array
set f [open $filename]
while {[gets $f line] >= 0} {
if {[regexp {^\s*set (\w+)=([""'']?)(.*)\2\s*$} $line -> key quote value]} {
set array($key) $value
}
}
close $f
}
This isn't complete code, since it doesn't handle substitution of variables inside the value, but it is enough to get you started. (I also hope you're not using that feature; if you are, portability is going to be quite a bit harder to achieve.) Here's how you'd use it:
#!/usr/bin/env tclsh
proc loadVariablesFromCshellFile {filename arrayName} {
upvar 1 $arrayName array
set f [open $filename]
while {[gets $f line] >= 0} {
if {[regexp {^\s*set (\w+)=([""'']?)(.*)\2\s*$} $line -> key quote value]} {
set array($key) $value
}
}
close $f
}
loadVariablesFromCshellFile vars.sh myvars
puts $myvars(a)
While it is entirely possible to load the values straight into scalar globals on the Tcl side, I really don't recommend it as it is polluting the global variable space from a source outside the Tcl program, a known piece of poor practice.

Powershell piping to variable and write-host at the same time

Hello all and thanks for your time in advance;
I'm running into a slight issue.
I'm running a command and piping it into a variable so i can manipulate the output.
$variable = some command
this normally works fine but doesn't output what's happening to the screen, which is fine most of the time. However occasionally this command requires some user input (like yes or no or skip for example), and since it's not actually piping anything to the command window, it just sits there hanging instead of prompting the user. If you know what to expect you can hit y or n or s and it'll proceed normally.
Is there anyway to run the command so that the output is piped to a variable AND appears on screen? I've already tried:
($variable = some command)
I've also tried:
write-host ($variable = some command)
But neither work. Note that the command running isn't a native windows or shell command and I cannot just run it twice in a row.
To clarify (because i probably wasn't clear)
I've also tried :
$variable = some command : Out-host
and
$variable = some command | out-default
with all their parameters, But the "prompt" from the command (to write y, n, s) doesn't show up.
Being able to pass S automatically would also be acceptable.
Sounds like you need Tee-Object. Example:
some command | Tee-Object -Variable MyVariable
This should pass everything from the command down the pipe, as well as store all output from the command in the $MyVariable variable for you.
You need to give some specific example that doesn't work. I tried this and it works:
function test { $c = read-host "Say something"; $c }
$x = test
I still see "Say something". read-host does not output to standard output so your problem is surprising. Even this works:
read-host "Say something" *> out
=== EDIT ===
Since this is interaction with cmd.exe you have two options AFAIK. First, test command:
test.cmd
#echo off
set /p something="Say something: "
echo %something%
This doesn't work as you said: $x= ./test.cmd
To make it work:
a) Replace above command with: "Say something:"; $x= ./test.cmd. This is obviously not ideal in general scenario as you might not know in advance what the *.cmd will ask. But when you do know its very easy.
b) Try this:
Start-transcript test_out;
./test.cmd;
Stop-transcript;
gc .\test_out | sls 'test.cmd' -Context 0,1 | select -Last 1 | set y
rm test_out
$z = ($y -split "`n").Trim()
After this $z variable contains: Say something: something. This could be good general solution that you could convert to function:
$z = Get-CmdOutput test.cmd
Details of text parsing might be slightly different in general case - I assumed here that only 1 question is asked and answer is on the same line but in any case with some work you will be able to get everything cmd.exe script outputed in general case:
=== EDIT 2 ===
This might be a better general extraction:
$a = gi test_out; rm test_out
$z = $a | select -Index 14,($a.count-5)
$z
$variable = ""
some command | % {$variable += $_;"$_"}
This executes the command, and each line of output is both added to $variable and printed to the console.

dcl assignment from a command

I am new to DCL.
I want to get the out put of a command in a variable and iterate result one by one.
filePath=dir /since="time_now" [.SUBDIR]*.PNG/noheader/notrail
That's just not how we roll with DCL.
We don't do pipes, we do, but not really.
DIR/SINCE=NOW ... will not give anything by definition, since nothing exists since now.
Use /OUT to stick the directory output into a file, and then read ans parse (F$PARSE and/or F$ELEMENT and/or F$LOC)
Check out HELP OPEN; HELP READ [/END]; HELP LEXICAL
Google for examples.
More advanced DCL scripts use F$PARSE, F$SEARCH and F$FILE(file,CDT) to avoid activating images and creating temp files: $ HELP LEXICAL
Google for examples.
Check out yesterday stack-exhange entry ?! : OpenVMS - DELETE Line if TEXT like x
But if you are just starting... IMHO just skip DCL and stick to PERL
$ perl -e "for (<[.SUBDIR]*.PNG>) { next unless -M > 0.123; print; ... }"
Good luck!
Hein
top:
file = f$search("[.subdir]*.PNG")
if (file .eqs. "")then goto cont
mtime=f$file_attribute(file,"RDT")
if mtime.ges.build_start_time then -
name=f>parse(file,,,"NAME")
call CHECK "''name'"
goto top
cont:
#Hein please review this code and suggest changes

Bash $PATH is caching every modification

How to clear the cache of $PATH in BASH. Every time I modify the $PATH, the former modifications are conserved too! So my $PATH is already one page :-), and it bothers me to work, because it points to some not right places (because every modification is being appended in the end of the $PATH variable). Please help me to solve this problem.
because every modification is being
appended in the end of the $PATH
variable
Take a close look at where you are setting $PATH, I bet it looks something like this:
PATH="$PATH:/some/new/dir:/another/newdir:"
Having $PATH in the new assignment gives you the appending behavior you don't want.
Instead do this:
PATH="/some/new/dir:/another/newdir:"
Update
If you want to strip $PATH of all duplicate entries but still maintain the original order then you can do this:
PATH=$(awk 'BEGIN{ORS=":";RS="[:\n]"}!a[$0]++' <<<"${PATH%:}")
PATH=$(echo $PATH | tr ':' '\n' | sort | uniq | tr '\n' ':')
Once in a while execute the above command. It will tidy up your PATH variable by removing any duplication.
-Cheers
PS: Warning: This will reorder the Paths in PATH variable. And can have undesired effects !!
When I'm setting my PATH, I usually use this script - which I last modified in 1999, it seems (but use daily on all my Unix-based computers). It allows me to add to my PATH (or LD_LIBRARY_PATH, or CDPATH, or any other path-like variable) and eliminate duplicates, and trim out now unwanted values.
Usage
export PATH=$(clnpath /important/bin:$PATH:/new/bin /old/bin:/debris/bin)
The first argument is the new path, built by any technique you like. The second argument is a list of names to remove from the path (if they appear - no error if they don't). For example, I have up to about five versions of the software I work on installed at any given time. To switch between versions, I use this script to adjust both PATH and LD_LIBRARY_PATH to pick up the correct values for the version I'm about to start using, and remove the values of the version I'm no longer using.
Code
: "#(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp $"
#
# Print minimal version of $PATH, possibly removing some items
case $# in
0) chop=""; path=${PATH:?};;
1) chop=""; path=$1;;
2) chop=$2; path=$1;;
*) echo "Usage: `basename $0 .sh` [$PATH [remove:list]]" >&2
exit 1;;
esac
# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN { # Sort out which path components to omit
chop="'"$chop"'";
if (chop != "") nr = split(chop, remove); else nr = 0;
for (i = 1; i <= nr; i++)
omit[remove[i]] = 1;
}
{
for (i = 1; i <= NF; i++)
{
x=$i;
if (x == "") x = ".";
if (omit[x] == 0 && path[x]++ == 0)
{
output = output pad x;
pad = ":";
}
}
print output;
}'
Commentary
The ':' is an ancient way of using /bin/sh (originally the Bourne shell - now as often Bash) to run the script. If I updated it, the first line would become a shebang. I'd also not use tabs in the code. And there are ways to get the 'chop' value set that do not involve as many quotes:
awk -F: '...script...' chop="$chop"
But it isn't broken, so I haven't fixed it.
When adding entries to PATH, you should check to see if they're already there. Here's what I use in my .bashrc:
pathadd() {
if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
PATH="$PATH:$1"
fi
}
pathadd /usr/local/bin
pathadd /usr/local/sbin
pathadd ~/bin
This only adds directories to PATH if they exist (i.e. no bogus entries) and aren't already there. Note: the pattern matching feature I use to see if the entry is already in PATH is only available in bash, not the original Bourne shell; if you want to use this with /bin/sh, that part'd need to be rewritten.
I have a nice set of scripts that add path variables to the beginning or end of PATH depending on the ordering I want. The problem is OSX starts with /usr/local/bin after /usr/bin, which is exactly NOT what I want (being a brew user and all). So what I do is put a new copy of /usr/local/bin in front of everything else and use the following to remove all duplicates (and leave ordering in place).
MYPATH=$(echo $MYPATH|perl -F: -lape'$_=join":",grep!$s{$_}++,#F')
I found this on perlmonks. Like most perl, it looks like line noise to me so I have no idea how it works, but work it does!

Open a piped process (sqlplus) in perl and get information from the query?

Basically, I'd like to open a pipe to sqlplus using Perl, sending a query and then getting back the information from the query.
Current code:
open(PIPE, '-|', "sqlplus user/password#server_details");
while (<PIPE>) {
print $_;
}
This allows me to jump into sqlplus and run my query.
What I'm having trouble figuring out is how to let Perl send sqlplus the query (since it's always the same query), and once that's done, how can I get the information written back to a variable in my Perl script?
PS - I know about DBI... but I'd like to know how to do it using the above method, as inelegant as it is :)
Made some changes to the code, and I can now send my query to sqlplus but it disconnects... and I don't know how to get the results back from it.
my $squery = "select column from table where rownum <= 10;"
# Open pipe to sqlplus, connect to server...
open(PIPE, '|-', "sqlplus user/password#server_details") or die "I cannot fork: $!";
# Print the query to PIPE?
print PIPE $squery;
Would it be a case of grabbing the STDOUT from sqlplus and then storing it using the Perl (parent) script?
I'd like to store it in an array for parsing later, basically.
Flow diagram:
Perl script (parent) -> open pipe into sqlplus (child) -> print query on pipe -> sqlplus outputs results on screen (STDOUT?) -> read the STDOUT into an array in the Perl script (parent)
Edit: It could be that forking the process into sqlplus might not be viable using this method and I will have to use DBI. Just waiting to see if anyone else answers...
Forget screen scraping, Perl has a perfectly cromulent database interface.
I think you probably want IPC::Run. You'll be using the start function to get things going:
my $h = start \#cat, \$in, \$out;
You would assign your query to the $input variable and pump until you got the expected output in the $output variable.
$in = "first input\n";
## Now do I/O. start() does no I/O.
pump $h while length $in; ## Wait for all input to go
## Now do some more I/O.
$in = "second input\n";
pump $h until $out =~ /second input/;
## Clean up
finish $h or die "cat returned $?";
This example is stolen from the CPAN page, which you should visit if you want more examples.
If your query is static consider moving it into it's own file and having sqlplus load and execute it.
open(my $pipe, '-|', 'sqlplus', 'user/password#server_details', '#/path/to/sql-lib/your-query.sql', 'query_param_1', 'query_param_2') or die $!;
while (<$pipe>) {
print $_;
}