string.find using directory path in Lua - perl

I need to translate this piece of code from Perl to Lua
open(FILE, '/proc/meminfo');
while(<FILE>)
{
if (m/MemTotal/)
{
$mem = $_;
$mem =~ s/.*:(.*)/$1/;
}
elseif (m/MemFree/)
{
$memfree = $_;
$memfree =~ s/.*:(.*)/$1/;
}
}
close(FILE);
So far I've written this
while assert(io.open("/proc/meminfo", "r")) do
Currentline = string.find(/proc/meminfo, "m/MemTotal")
if Currentline = m/MemTotal then
Mem = Currentline
Mem = string.gsub(Mem, ".*", "(.*)", 1)
elseif m/MemFree then
Memfree = Currentline
Memfree = string.gsub(Memfree, ".*", "(.*)", 1)
end
end
io.close("/proc/meminfo")
Now, when I try to compile, I get the following error about the second line of my code
luac: Perl to Lua:122: unexpected symbol near '/'
obviously the syntax of using a directory path in string.find is not like how I've written it. 'But how is it?' is my question.

You don't have to stick to Perl's control flow. Lua has a very nice "gmatch" function which allows you to iterate over all possible matches in a string. Here's a function which parses /proc/meminfo and returns it as a table:
function get_meminfo(fn)
local r={}
local f=assert(io.open(fn,"r"))
-- read the whole file into s
local s=f:read("*a")
-- now enumerate all occurances of "SomeName: SomeValue"
-- and assign the text of SomeName and SomeValue to k and v
for k,v in string.gmatch(s,"(%w+): *(%d+)") do
-- Save into table:
r[k]=v
end
f:close()
return r
end
-- use it
m=get_meminfo("/proc/meminfo")
print(m.MemTotal, m.MemFree)

To iterate a file line by line you can use io.lines.
for line in io.lines("/proc/meminfo") do
if line:find("MemTotal") then --// Syntactic sugar for string.find(line, "MemTotal")
--// If logic here...
elseif --// I don't quite understand this part in your code.
end
end
No need to close the file afterwards.

Related

How do I rewrite a text file on the same columns in perl?

I have an ncl script which I modify inside a perl script, each time I run the Perl script and then call the same ncl script within the perl script.
What I have noticed is that each time I run the perl script, the lines in the ncl script are progressively rewritten to the right. I wonder how far they will go to the right and if the ncl script will still work if the move very far to the right.
I am wondering if it is possible to specify the column from which to start writing. I have no idea if there is a solution to this, apart from manually boving the lines back.
Below are the changes I make to the script.
open($NCLSCRPT, " < /home/zmumba/DA/TMINTMAX/Scripts/10_PlotT2mMinMax.ncl") || die "open $NCLSCRPT: failed $! ($^E)";
#scrptlines=<$NCLSCRPT>;
foreach $scrptlines (#scrptlines) {
if ($scrptlines =~ /(^|\s+)a = addfile/) {
$scrptlines =~ s/\w+\.nc/Tmin.nc/g;
}
if ($scrptlines =~ /wks = gsn_open_wks/) {
$scrptlines =~ s/\w+_\d{2}/Tmin_$day/g;
}
$scrptlines =~ s/\w+ Temperature/Minimum Temperature/g;
if ($scrptlines =~ /Valid on/) {
$scrptlines =~ s/$valdate/${day}\/${month}\/${year}/g;
}
if ($scrptlines =~ /From 00z on/) {
$scrptlines =~ s/$wrffcr/T\+00H/g;
$scrptlines =~ s/$valdate/${day}\/${month}\/${year}/g;
}
}
close $NCLSCRPT;
open($NCLSCRPT, " > /home/zmumba/DA/TMINTMAX/Scripts/10_PlotT2mMinMax.ncl") || die "open $NCLSCRPT: failed $! ($^E)";
print $NCLSCRPT "#scrptlines\n";
close $NCLSCRPT;
To do justice, i am adding a part of the text file I am processing as per request from #Håkon Hægland.
Otherwise the problem has been resolved.
begin
;Open input file.
;************************
DATADir = "./"
a = addfile(DATADir+"Tmax.nc","r")
T = wrf_user_getvar(a,"T2",0)
T = T-273.15
wrf_smooth_2d( T, 3 ) ; smooth T
;printVarSummary(T)
;exit
lat2d = a->XLAT(:,:)
lon2d = a->XLONG(:,:)
lat = lat2d(:,0) ; create classic 1D coordinate arrays
lon = lon2d(0,:)
lat#units= "degrees_north"
lon#units= "degrees_east"
lat!0 = "lat"
lon!0 = "lon"
lat&lat = lat
You are adding spaces with your final print:
print $NCLSCRPT "#scrptlines\n";
When you interpolate an array into a string, each element is padded with a space (default value of the $" variable). So, when you take the lines from a file, and continuously interpolate them this way, you will add spaces.
It should instead be
print $NCLSCRPT #scrptlines;
If you never edit the line endings, you don't need to worry about them.

Opening a file inside a subroutine for read/write in Perl

I am trying to open a file inside a subroutine to basically substitute some lines in the file. But since, it was not working, I tried a simpler way of printing a line instead of substitute, for debug purposes. Following is the subroutine code.
sub replace {
while (<INPUT_FILE>){
my $cell = $_[0];
our $rpl;
if ($_=~ /^TASK\|VALUE = (.*)/ ) {
my $task = $1;
chomp $task;
$rpl = $cell . '_' . $task . '_bunch_rpl';
print "000: $rpl\n";
}
elsif ($_=~ /^(.*)\|VALUE = (.*)/ ) {
my $line = $_;
chomp $line;
my $ip_var = $1;
my $ip_val = $2;
chomp $ip_var;
chomp $ip_val;
my $look= $ip_var."|VALUE";
open(REPLAY_FILE, "+<$rpl") || die "\ncannot open $rpl\n";
while (my $rpl_sub = <REPLAY_FILE>) {
if ($rpl_sub =~ /^$line/) {
print "\n 111: $ip_val";
}
}
close REPLAY_FILE;
}
elsif ($_=~ /^\s*$/) {
print "\n";
return ;
}
}
}
The code prints the following as of now.
000: lfr_task62_bunch_rpl
111: 2.0.9.0
111: INLINE
111: POWER
000: aaa_task14_bunch_rpl
Expected output is:
000: lfr_task62_bunch_rpl
111: 2.0.9.0
111: INLINE
111: POWER
000: aaa_task14_bunch_rpl
111: 0.45
111: NO
The input sample is:
TASK_CELL_NAME|VALUE = lfr
TASK|VALUE = task62
TASK_VERSION|VALUE = 2.0.9.0
CHIP_PKG_TYPE|VALUE = INLINE
JUNK_LINE = JUNK
JUNK_LINE = JUNK
FULL_ESD|VALUE = POWER
TASK_CELL_NAME|VALUE = aaa
TASK|VALUE = task14
CUSTOM_CELL_DENSITY|VALUE = 0.45
CUSTOM_CELL_SS|VALUE = NO
Can someone tell me the mistake I am doing here?
UPDATE: Main code below
my #cell_names;
open(INPUT_FILE, "<$ip_file") || die "\n!!!ERROR OPENING INPUT FILE. EXITING SCRIPT!!!\n";
while (<INPUT_FILE>) {
if ($_=~ /(.*) =\n/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /(.*) =\s+\n/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /(.*) = \s+(.*)/ ) {
$mw -> messageBox(-message=> "\nFormat not correct on line $. of input file. Exiting script\n");
exit;
}
elsif ($_=~ /^TASK_CELL_NAME\|VALUE = (.*)/ ) {
my $cell_name = $1;
chomp $cell_name;
unless(grep( /^$cell_name $/, #cell_names )) {
push #cell_names, "$cell_name ";
#$count++;
#print "\nCELL NAME: $cell_name\n";
replace($cell_name);
}
}
}
close INPUT_FILE;
Update: lfr_task62_bunch_rpl before running code:
# Select fund
FUND|VALUE = mmi
# Select bank
BANK|VALUE = citi
# Select cell name
TASK_CELL_NAME|VALUE = lfr
# Select task
TASK|VALUE = task62
# Select task version
TASK_VERSION|VALUE = 1.0.9.0
# Select fund type
FULL_ESD|VALUE = MUTUAL
# Select customer premium
CUSTOM_CELL_SS|VALUE = YES
# Select customer brand density
CUSTOM_CELL_DENSITY|VALUE = 0.76
# Select card chip
CHIP_PKG_TYPE|VALUE|VALUE = OUTLINE
Expected lfr_task62_bunch_rpl after running code:
# Select fund
FUND|VALUE = mmi
# Select bank
BANK|VALUE = citi
# Select cell name
TASK_CELL_NAME|VALUE = lfr
# Select task
TASK|VALUE = task62
# Select task version
TASK_VERSION|VALUE = 2.0.9.0
# Select fund type
FULL_ESD|VALUE = POWER
# Select customer premium
CUSTOM_CELL_SS|VALUE = YES
# Select customer brand density
CUSTOM_CELL_DENSITY|VALUE = 0.76
# Select card chip
CHIP_PKG_TYPE|VALUE|VALUE = INLINE
It's not really clear what this code is supposed to do. But I can immediately see a few problems with the logic. Let's step through a few iterations of the loop, using your sample data file.
The first time, the line of data read in is:
TASK_CELL_NAME|VALUE = lf
So that matches on your second regex match. You set a few variables and then (because $ip_var is equal to "TASK_CELL_NAME") you skip to the else clause and close a filehandle that isn't open.
Next time round, we read:
TASK|VALUE = task62
That matches your first regex match. The variable $rpl_file is set to "XXX_lfr_bunch_rpl" (where 'XXX' is the parameter passed to the subroutine - obviously, I don't know what that is). You print a "000" line with that value and open the file with that name in r/w mode.
Third time round, we get this data:
TASK_VERSION|VALUE = 2.0.9.0
This matches your second regex and because $ip_var isn't equal to "TASK_CELL_NAME" we go into the if clause. This reads from your open filehandle and prints a "111" line. But this generates a warning if you have use warnings switched on as the line includes the value of $rpl_file which is currently defined. It was set the last time around the loop, but because the variable is declared inside the loop, it has now lost its value. We then close the filehandle.
The fourth iteration will be the last one that's really interesting. We get this data:
CHIP_PKG_TYPE|VALUE = INLINE
This also matches the second regex, so we do a lot the same as the third iteration. But the difference here is that when we try to read from the filehandle, we get a warning because that filehandle is closed. Oh, and then we close it again for good measure :-)
As I said at the start, I can't really work out what we're trying to do here. But I can see that the logic is very strange. You really need to go back to the drawing board and think through your logic again.
Update:
With the updated version of your code, I'm still seeing problems.
On the first iteration, the data is:
TASK_CELL_NAME|VALUE = lf
So this matches your second regex. That goes into the piece of code that opens the other file and tries to read from it. But it expects to find the filename in $rpl and that variable hasn't been given a value yet. So the open() fails and the program dies.

Considering all the actual arguments given to a perl function as scalar

I have a perl script generator.pl that defines some routines like:
sub a($) {
...
print FILE "$_[0]";
...
}
...
sub b($$) {
...
print FILE "$_[0], $_[1]";
...
}
...
$subsfile = $ARGV[0] . "/subs.pl";
$generatedfile = $ARGV[0] . "/generated.file";
open FILE, '>>', "$generatedfile" or die "error trying to append: $!";
do "$subsfile";
close FILE;
Let's assume that, for example subs.pl is like this:
a(1);
a(x);
b(1-2, z);
b(1-x, i);
b(y-z, j);
I call generator script in this way:
C:\Users\Me>perl generator.pl "D:/another/path"
Result is that D:/another/path/generated.file is created but it contains 0 bytes. Printing "print $#;" after do statement, I'm obtaining:
Transliteration pattern not terminated at...
If I try to call the script with a subs.pl having each actual argument double quoted
a("1");
a("x");
b("1-2", "z");
b("1-x", "i");
...
it works.
How can I do to make things work without using double quotes?
tr/// is transliteration operator which can be also written as y///. Further, it can be modified to take another character as delimiter, ie. y---.
So when perl see something like,
b(y-z, j);
it expects
b(y-z, j--);
which is correct and would in example above count all occurrences of z, ,, , and j chars in default variable $_, and pass it as argument to b().
Since compiler expectations are not met, it throws:
Transliteration pattern not terminated at...

understanding a simple Perl construct

as a not Perl programmer, i would like to be sure i had well understood a construct that i am going to port to Python,
when using :
if (s/^([$PChar])(.)/$2/) {
print $1,"\n";
$finished = 0;
}
$1, $2 etc. are matching regular expression
s/search for/replace with/
what i am really not sure is does the matching/replacement is done before the print $1 ? and is it done "inplace" inside current buffer (which is $F, that is $_ line by line readed, splitted on its space character), that is changing it (so if i understand well, the ([$PChar]) when # beginning of a string is totally striped off/lost in the above statment) ?
EDIT : no maybe it is not lost, first parenthesis part is captured, and then printed as $1 + new line character and then... no, do not understand what become $2... may be buffer change to second parenthesis part ? /END OF EDIT.
also is there any environnement or what is the best environnement that permit to do some step-by-step debugging on Win platform ? i'm aware that having this, i will not have asked this question. And i do not need to learn Perl, just only to be able to read and adapt this script.
here is the englobing part :
#F = split;
for( $j=0; $j<=$#F; $j++) {
my $suffix="";
$_ = $F[$j];
# separate punctuation and parentheses from words
do {
$finished = 1;
# cut off preceding punctuation
if (s/^([$PChar])(.)/$2/) {
print $1,"\n";
$finished = 0;
}
# cut off trailing punctuation
if (s/(.)([$FChar])$/$1/) {
$suffix = "$2\n$suffix";
$finished = 0;
}
whole script tokenize.pl can be seen here while original tar.bz if from here
best regards
# try to delete the first character from the string contained in
# $_ if that character is one of the characters contained in
# the string $PChar. The deletion is done by replace the first and
# second character by only the second character.
if (s/^([$PChar])(.)/$2/) {
# if the replacement was successful, print the deleted character.
print $1,"\n";
$finished = 0;
}

Perl program for extracting the functions alone in a Ruby file

I am having the following Ruby program.
puts "hai"
def mult(a,b)
a * b
end
puts "hello"
def getCostAndMpg
cost = 30000 # some fancy db calls go here
mpg = 30
return cost,mpg
end
AltimaCost, AltimaMpg = getCostAndMpg
puts "AltimaCost = #{AltimaCost}, AltimaMpg = {AltimaMpg}"
I have written a perl script which will extract the functions alone in a Ruby file as follows
while (<DATA>){
print if ( /def/ .. /end/ );
}
Here the <DATA> is reading from the ruby file.
So perl prograam produces the following output.
def mult(a,b)
a * b
end
def getCostAndMpg
cost = 30000 # some fancy db calls go here
mpg = 30
return cost,mpg
end
But, if the function is having block of statements, say for example it is having an if condition testing block means then it is not working. It is taking only up to the "end" of "if" block. And it is not taking up to the "end" of the function. So kindly provide solutions for me.
Example:
def function
if x > 2
puts "x is greater than 2"
elsif x <= 2 and x!=0
puts "x is 1"
else
puts "I can't guess the number"
end #----- My code parsing only up to this
end
Thanks in Advance!
If your code is properly indented, you just want lines that start with def or end, so change your program to:
while (<DATA>){
print if ( /^def/ .. /^end/ );
}
Or run it without a program file at all - run the program from the command line, using -n to have perl treat it as a while loop reading from STDIN:
perl -n -e "print if ( /^def/ .. /^end/ );" < ruby-file.rb
I am not familiar with ruby syntax but if you can ensure good indentation all over the code, you can check based on indentation. Something similar to:
my $add = 0;
my $spaces;
while(my $str = <DATA>) {
if (! $add && $str =~ /^(\s*)def function/) {
$add = 1;
$spaces = $1;
}
if ($add) {
print $_;
$add = 0 if ($str =~ /^$spaces\S/);
}
}
Another option could be counting level of program, something like this:
my $level = 0;
while(<DATA>) {
if(/\b def \b/x .. /\b end \b/x && $level == 0) {
$level++ if /\b if \b/x; # put all statements that closes by end here
$level-- if /\b end \b/x;
print;
}
}
I am not all that familiar with ruby syntax, so you need to put all statements that are closed by end into regex with $level++.
Please note I added \b around those keywords to make sure you are matching whole word and not things like undef as start of function.