Is it possible to use perl to remove parameters from a function definition? eg if my file contains the following text:
var1 = myfunc(sss,'ROW DRILL',1,1,0);
var2 = myfunc(fff,'COL DRILL',1,1,0);
var3 = myfunc(anyAlphaNum123,'anyAlphaNum123 or space',1,1,0);
donotcapture=myfunc2(rr,'some string',1,1,0);
I need to change it so that it becomes:
var1 = myfunc(sss,'ROW DRILL');
var2 = myfunc(fff,'COL DRILL');
var3 = myfunc(anyAlphaNum123,'anyAlphaNum123 or space');
donotcapture=myfunc2(rr,'some string',1,1,0);
Essentially just removing ,1,1,0 from all instances where myfunc is called, but preserving the first two parameters.
I have tried the following, but this approach would mean I have to write rules for each permutation...
perl -pi -w -e "s/myfunc\(rr,'COL SUBSET',1,1,0\)/myfunc\(rr,'COL SUBSET'\)/g;" *.txt
In order to reduce complexity, generalize your regex, using flexible regexes.
The regex for "anything between ( and ,, except , " : \(([^,]+),
The regex for "anything between ' and ', except ' " : \'([^']+)\'
In order to get the output right for the specific input (in spite of the flexibility),
use capture groups, i.e. (...).
They populate variables, which you can use as $1 in the substitution.
To prevent matching functions with names ending in your functions name, e.g. notmyfunc(),
use the regex for word boundary, i.e. \b.
Ikegamis edit (separated to keep visible what you and I learned the hard way):
Avoid double-quotes for the program argument.
It's just asking for trouble and requires so much extra escaping.
Note that \x27 is a single quote when used inside double-quotes or regex literals.
\' -> \x27
Only use one capture group (myfunc\([^,]+,\x27[^\x27]+\x27)
Remove the ;, which is not needed for a single statement.
Add a . to the input file wildcard, assuming you actually meant it like that.
Working code
(Comparing to chat note the \((; the backslash got lost, eaten by the chat I believe.):
perl -pi -w -e "s/(\bmyfunc)\(([^,]+),\'([^']+)\'(?:,\d+){3}\)/\$1\(\$2,\'\$3\'\)/g;" *txt
Ikegamis nice edit
(The detail which was so time-consuming in our chat is not easily visible anymore,
because the ( for the capture group was moved somewhere else.):
perl -i -wpe's/\b(myfunc\([^,]+,\x27[^\x27]+\x27)(?:,\d+){3}\)/$1)/g' *.txt
Input:
var1 = myfunc(sss,'ROW DRILL',1,1,0);
var2 = myfunc(fff,'COL DRILL',1,1,0);
var3 = myfunc(s,'ROW SUBSET',1,1,0);
var4 = myfunc(rr,'COL SUBSET',1,1,0);
var5 = myfunc(rr,'COL SUBSET',2,12,50); with different values
var6 = notmyfunc(rr,'COL SUBSET',1,1,0); tricky differet name
var1 = myfunc(sss,'ROW DRILL',1,1,0);
var2 = myfunc(fff,'COL DRILL',1,1,0);
var3 = myfunc(anyAlphaNum123,'anyAlphaNum123 or space',1,1,0);
donotcapture=myfunc2(rr,'some string',1,1,0);
Output (version "even more relaxed"):
var1 = myfunc(sss,'ROW DRILL');
var2 = myfunc(fff,'COL DRILL');
var3 = myfunc(s,'ROW SUBSET');
var4 = myfunc(rr,'COL SUBSET');
var5 = myfunc(rr,'COL SUBSET'); with different values
var6 = notmyfunc(rr,'COL SUBSET',1,1,0); tricky differet name
var1 = myfunc(sss,'ROW DRILL');
var2 = myfunc(fff,'COL DRILL');
var3 = myfunc(anyAlphaNum123,'anyAlphaNum123 or space');
donotcapture=myfunc2(rr,'some string',1,1,0);
Lessons learned:
I made a habit of creating regexes as tightly fitting the input as possible.
But that caught us/me unprepared, when applied to sample input by someone inexperienced with regexes. (Absolutely no blame on you.)
Posting code-quotes into chat is dangerous, be careful with \.
Related
Suppose I have a char variable in Matlab like this:
x = 'hello ### my $ name is Sean Daley.';
I want to replace the first '###' with the char '&', and the first '$' with the char '&&'.
Note that the character groups I wish to swap have different lengths [e.g., length('###') is 3 while length('&') is 1].
Furthermore, if I have a more complicated char such that pairs of '###' and '$' repeat many times, I want to implement the same swapping routine. So the following:
y = 'hello ### my $ name is ### Sean $ Daley ###.$.';
would be transformed into:
'hello & my && name is & Sean && Daley &.&&.'
I have tried coding this (for any arbitrary char) manually via for loops and while loops, but the code is absolutely hideous and does not generalize to arbitrary character group lengths.
Are there any simple functions that I can use to make this work?
y = replace(y,["###" "$"],["&" "&&"])
The function strrep is what you are looking for.
A very short question. I have a string
str = 'var(:,1),var(:,2),var(:,3)';
I need to split it with strsplit by ',' but not by ':,' so that I will end up with a cell array
cel = {'var(:,1)','var(:,2)','var(:,3)'};
I am not good with regular expression at all and I tried ,^(:,) but this fails. I thought ^ is not () is group.
How can it be done?
Use a regular expression with negative lookbehind:
cel = regexp(str, '(?<!:),', 'split');
I have few similar questions about expressions. I marked them as Q1, Q2 and Q3 for convenience.
First. As stated in the docs,
Variable names in an expression are not enclosed in percent signs (except for pseudo-arrays and other double references). Consequently, literal strings must be enclosed in double quotes to distinguish them from variables.Source
As I understand, this means we should write code like this:
a = aaa
b = zzz
if (a = "aaa" or b = "bbb")
MsgBox, It works!
However, this seems also works:
a = aaa
b = zzz
if (%a% = aaa or %b% = bbb)
MsgBox, It works!
Is there some drawbacks in the second way? (Q1)
One possible drawback, which I found myself, is that second method will not work if variable contains only digits. This will not work:
a = 111
b = 999
if (%a% = 111 or %b% = 222)
MsgBox, It works!
Why it stopped worked now? (Q2)
And also, if variable contains only digits, there seems no need to quote it's value in expression:
a = 111
if (a = "111") ; Also works for a = "aaa"
MsgBox, It works!
a = 111
if (a = 111) ; It will not work for a = "aaa". We forced to us quote signs if var contains letters.
MsgBox, It works too.
Why second way (if (a = 111)) works and should or should not we avoid it? (Q3).
(Q1)
If a variable is enclosed in percent signs within an expression (in your example %a%), whatever that variable contains is assumed to be the name or partial name of another variable.
This also works
a = aaa
b = zzz
if (%a% = a or %h% = cc)
MsgBox, It works!
because the values of the vars %a% and %h% are not specified.
(Q2)
If both var and value are purely numeric, they will be compared as numbers rather than as strings.
Otherwise, they will be compared alphabetically as strings (that is, alphabetical order will determine whether var is greater, equal, or less than value).
(Q3)
Only literal strings must be enclosed in double quotes.
If the variable contains only digits, there is no need to quote.
I have a string of variable names as shown below:
{'"NORM TIME SEC, SEC, 9999997" "ROD FORCE, LBS, 3000118" "ROD POS, DEG, 3000216" P_ext_chamber_press P_ret_chamber_press "GEAR#1 POS INCH" 388821 Q_valve_gpm P_return 3882992 "COMMAND VOLTAGE VOLT"'}
the double quotes are for the variable names with spaces or special characters between the words" and a single word variable doesn't have any quotes around them. The variables are separated by one space. Some variable names are just numbers.
At the end, I want to create a cell with strings as follows:
{'NORM_TIME_SEC_SEC_9999997','ROD_FORCE_LBF_3000118','ROD_POS_DEG_3000216','P_ext_chamber_press','P_ret_chamber_press','GEAR#1_POS_INCH','3388821','Q_valve_gpm','P_return','3882992','COMMAND_VOLTAGE_VOLT'}
You can use regexp to first split it into groups and then replace all space with _
data = {'"abc def ghi" "jkl mno pqr" "stu vwx" yz"'};
% Get each piece within the " "
pieces = regexp(data{1}, '(?<=\"\s*)([A-Za-z0-9]+\s*)*(?=\"\s*)', 'match');
% 'abc def ghi' 'jkl mno pqr'
% Replace any space with _
names = regexprep(pieces, '\s+', '_');
% 'abc_def_ghi' 'jkl_mno_pqr'
Update
Since your last variable isn't surrounded by quotes, you could do something like the following
pieces = strtrim(regexp(data, '[^\"]+(?=\")', 'match'));
pieces = pieces{1};
pieces = pieces(~cellfun(#isempty, pieces));
% Replace spaces with _
regexprep(pieces, '\s+', '_')
I ended up forcing myself to study little bit on regular expression and the following seems to be working well for what I'm trying to do:
regexp(str,'(\"[\w\s\,\.\#]+\"|\w+)','match')
Probably not as robust as I want since I'm specifically singling out a certain set of special characters only, but so far, I haven't seen other special characters other than those in the data sets I have.
str = {'"abc def ghi" "jkl mno pqr" "stu vwx" yz"'};
Then
str_u = strrep(str,' ','_');
[str_q rest] = strtok(str_u,'"');
str_u = rest;
while ~strcmp(rest,'')
[token rest] = strtok(str_u,'"');
if ~(strcmp(token,'_')||strcmp(token,''))
if strcmp(token{1,1}(1),'_')
token{1,1} = strrep(token{1,1},'_','');
end
str_q = [str_q, token];
end
str_u = rest;
end
The resultant cell array is str_q, which will give the names of the variables
str_q = 'abc_def_ghi' 'jkl_mno_pqr' 'stu_vwx' 'yz'
Here is my naive approach:
# puppet/init.pp
$x = 'hello ' +
'goodbye'
This does not work. How does one concatenate strings in Puppet?
Keyword variable interpolation:
$value = "${one}${two}"
Source: http://docs.puppetlabs.com/puppet/4.3/reference/lang_variables.html#interpolation
Note that although it might work without the curly braces, you should always use them.
I use the construct where I put the values into an array an then 'join' them.
In this example my input is an array and after those have been joined with the ':2181,' the resulting value is again put into an array that is joined with an empty string as separator.
$zookeeperservers = [ 'node1.example.com', 'node2.example.com', 'node3.example.com' ]
$mesosZK = join([ "zk://" , join($zookeeperservers,':2181,') ,":2181/mesos" ],'')
resulting value of $mesosZK
zk://node1.example.com:2181,node2.example.com:2181,node3.example.com:2181/mesos
Another option not mentioned in other answers is using Puppet's sprintf() function, which functions identically to the Ruby function behind it. An example:
$x = sprintf('hello user %s', 'CoolUser')
Verified to work perfectly with puppet. As mentioned by chutz, this approach can also help you concatenate the output of functions.
The following worked for me.
puppet apply -e ' $y = "Hello" $z = "world" $x = "$y $z" notify { "$x": } '
notice: Hello world
notice: /Stage[main]//Notify[Hello world]/message: defined 'message' as 'Hello world'
notice: Finished catalog run in 0.04 seconds
The following works as well:
$abc = "def"
file { "/tmp/$abc":
You could use the join() function from puppetlabs-stdlib. I was thinking there should be a string concat function there, but I don't see it. It'd be easy to write one.
As stated in docs, you can just use ${varname} interpolation. And that works with function calls as well:
$mesosZK = "zk://${join($zookeeperservers,':2181,')}:2181/mesos"
$x = "${dirname($file)}/anotherfile"
Could not use {} with function arguments though: got Syntax error at '}'.