In fish shell, how to iterate over files using wildcard and variable? - fish

If I run:
for f in *1000.png
echo $f
end
I get
1000.png
11000.png
21000.png
I would like to do something like:
for i in 1 2 3
for f in *$i000.png
echo $f
end
end
To get
1000.png
11000.png
21000.png
2000.png
12000.png
22000.png
3000.png
13000.png
23000.png
Instead, it outputs nothing.
I also tried:
for i in 1 2
set name "*"$i"000.png"
for f in (ls $name)
echo $f
end
end
Outputting:
ls: *1000.png: No such file or directory
ls: *2000.png: No such file or directory

To avoid trying to expand the variable $i000, you would do
for i in 1 2 3
for f in *{$i}000.png
echo $f
end
end
Or, avoid the outer loop altogether:
for f in *{1,2,3}000.png

When you are attempting to referencing the i variable in *$i000.png, your shell thinks that $i000 means you are trying to reference the i000 variable, not i followed by three zeroes like you want.
Use {$var_name} to access variables in fish, generally its a good idea to always reference shell variables this way.
So your your case, in the second line use:
for f in *{$i}000.png

Related

Autofiltering Excel with multiple filter conditions

I am trying to autofilter in Excel using the below VBScript code. This script called multiple times from a Perl program.
Dim objExcel : Set objExcel = GetObject(,"Excel.Application")
objExcel.Visible = True
objExcel.Selection.AutoFilter
objExcel.ActiveSheet.Range("G1").AutoFilter WScript.Arguments.Item(0), _
WScript.Arguments.Item (1)
Now I would like to know: is there a way by which I can pass an array for WScript.Arguments.Item (1) so that all the conditions are selected in one go? The task is to delete the filtered value. I call this script through Perl multiple times and the above script filter one value at a time and delete. The program works fine, but is slow.
Following is the part of Perl which calls the VBScript.
while(<FILE>){
chomp;
system("CSCRIPT "."\"$currentWorkingDirectory\"".'aboveVBS.vbs 9 '."\"$_\"");
sleep(2);
}
If you put quotes around the values, VBScript will treat it as a single argument.
> cscript script.vbs arg1 "multiple values for arg 2"
In the script:
WScript.Echo WScript.Arguments.Count ' ==> 2
a = Split(WScript.Arguments(1))
WScript.Echo a(0) ' ==> multiple
WScript.Echo a(1) ' ==> values
WScript.Echo a(2) ' ==> for
WScript.Echo a(3) ' ==> arg
WScript.Echo a(4) ' ==> 2
Excel expects:
Range.AutoFilter <Field>, <Criteria>, <Operator>
If you want a list of criteria to filter on, you'll use xlFilterValues for the <Operator> argument. <Criteria> will be an array of string values, which we created above.
Const xlFilterVaues = 7
objExcel.ActiveSheet.Range("G1").AutoFilter WScript.Arguments.Item(0), a, xlFilterValues
So, just try adding Split() around WScript.Arguments(1) in your existing code, and pass xlFilterValues for the third param.
If only your second argument changes, you could pass the entire content of your data file to the VBScript:
local $/;
my $args = <FILE>;
$args =~ s/^\s+|\s+$//g;
$args =~ s/\r?\n/" "/g;
system("cscript \"$currentWorkingDirectory\\your.vbs\" 9 \"$args\"");
and change the processing in your VBScript to this:
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set wb = xl.Workbook.Open("C:\path\to\your.xlsx")
Set ws = wb.Sheets(1)
...
xl.Selection.AutoFilter
For i = 1 To WScript.Arguments.Count - 1
ws.Range("G1").AutoFilter WScript.Arguments(0), WScript.Arguments(i)
...
Next
Or you could simply call the VBScript with the field and the path to the data file:
system("cscript \"$currentWorkingDirectory\\your.vbs\" 9 \"$filepath\"");
and do all the processing in VBScript:
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set wb = xl.Workbook.Open("C:\path\to\your.xlsx")
Set ws = wb.Sheets(1)
...
xl.Selection.AutoFilter
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(WScript.Arguments(1))
Do Until f.AtEndOfStream
ws.Range("G1").AutoFilter WScript.Arguments(0), f.ReadLine
...
Next
f.Close
Applying more than 2 AutoFilter conditions to a column at the same time is not possible. Check the signature of the AutoFilter method in the documentation:
expression .AutoFilter(Field, Criteria1, Operator, Criteria2, VisibleDropDown)
expression An expression that returns a Range object.
You have Critera1 and Criteria2 and an Operator for combining the two. Calling the AutoFilter method with another set of criteria replaces the existing criteria.

How can I use sed to to convert $$ blah $$ in TeX to \begin{equation} blah \end{equation}

I have files with entries of the form:
$$
y = x^2
$$
I'm looking for a way (specifically using sed) to convert them to:
\begin{equation}
y = x^2
\end{equation}
The solution should not rely on the form of the equation (which may also span mutiple lines) nor on the text preceding the opening $$ or following the closing $$.
Thanks for the help.
sed '
/^\$\$$/ {
x
s/begin/&/
t use_end_tag
s/^.*$/\\begin{equation}/
h
b
: use_end_tag
s/^.*$/\\end{equation}/
h
}
'
Explanation:
sed maintains two buffers: the pattern space (pspace) and the hold space (hspace). It operates in cycles, where during each cycle it reads a line and executes the script for that line. pspace is usually auto-printed at the end of each cycle (unless the -n option is used), and then deleted before the next cycle. hspace holds its contents between cycles.
The idea of the script is that whenever $$ is seen, hspace is first checked to see if it contains the word "begin". If it does, then substitute the end tag; otherwise substitute the begin tag. In either case, store the substituted tag in the hold space so it can be checked next time.
sed '
/^\$\$$/ { # if line contains only $$
x # exchange pspace and hspace
s/begin/&/ # see if "begin" was in hspace
t use_end_tag # if it was, goto use_end_tag
s/^.*$/\\begin{equation}/ # replace pspace with \begin{equation}
h # set hspace to contents of pspace
b # start next cycle after auto-printing
: use_end_tag
s/^.*$/\\end{equation}/ # replace pspace with \end{equation}
h # set hspace to contents of pspace
}
'
This might work for you (GNU sed):
sed -r '1{x;s/^/\\begin{equation}\n\\end{equation}/;x};/\$\$/{g;P;s/(.*)\n(.*)/\2\n\1/;h;d}' file
Prime the hold space with the required strings. On encountering the marker print the first line and then swap the strings in anticipation of the next marker.
I can not help you with sed, but this awk should do:
awk '/\$\$/ && !f {$0="\\begin{equation}";f=1} /\$\$/ && f {$0="\\end{equation}";f=0}1' file
\begin{equation}
y = x^2
\end{equation}
The f=0is not needed, if its not repeated.

How to parse variable in REXX/Regina

When writing a macro, I have a variable, {$#2}, that either starts with a 1 or 2 digit number followed by a ".", or it doesn't. When it starts in that way, I want to put the number into a rexxvar, which I have called C.
I have tried
#if [ DATATYPE(LEFT({$#2},1), "W") ] \
#evaluate ^^ ^parse '{$#2} C '.' .^ \
#endif \
This, and every variation I can think of, gives errors saying the #IF line contains invalid characters.
How should I do this?
I am using PPWizard, and Regina - but I can't create either tag.
Thanks
Ian
I do not use PPWizard so this could all be wrong, but
Looking at PPWizard #if, the if should be either
#if DATATYPE(LEFT({$#2},1), "W")
or
#if [ DATATYPE(LEFT({$#2},1), "W") <> 0 ]
But I do not know wether you can imbed the {$#2} or not (I do not know PPWizard)
For the parse statement one of these may be what you want
#evaluate ^^ ^parse value '{$#2}' with C '.' .^
or
#evaluate ^^ ^parse var {$#2} C '.' .^
See rexx parse syntax
An alternative way might try the Define Rexx tag and do it in rexx. More people could help you with pure rexx. i.e the rexx would be
if DATATYPE(LEFT(value_to_process,1), "W") then do
parse var value_to_process C '.'
end
where value_to_process is the value to be checked (i.e. {$#2})
For others.
The final answer to the problem is to write
#RexxVar value_to_process = {$#2}
#evaluate+ ^^ ^if DATATYPE(LEFT(value_to_process,1), "W") then do; parse var value_to_process C '.'; end^ \
in the macro I was creating.
Thanks Bruce. Your reply was most helpful on my route to a solution.

How to store the line matching an expression in matlab

I have the following code, and i am wanting to store the entire line that contains the matching expression, but currently i am able to store only the expression itself.
expr='\hello';
fileread = regexp(filetext, expr, 'match');
fid = fopen('data.txt', 'wt');
fprintf(fid, '%s\n',fileread{:});
suppose my file contains:
Hello,my name is X
X hello
Not this line
my file data.txt stores
hello
hello
instead of the entire line containing the expression.
desired data.txt
Hello,my name is X
X hello
what am i doing wrong?
Based on the way you are interacting with the regexp function I will assume you have all the file text in a single variable. Let's imagine that variable takes the following form:
my name is hello there
Hello,my name is X
X hello
Not this line
For your reference, I've constructed this variable using sprintf
string = sprintf('my name is hello there\nHello,my name is X\n X hello\n Not this line')
You can extract the lines which have hello with the following regexp:
[~,~,~,d] = regexp(string, '.*?[H|h]ello.*?\n')
The results can be retrieved from the cell array with:
>> d{1}
ans =
my name is hello there
>> d{2}
ans =
Hello,my name is X
>> d{3}
ans =
X hello
Note that I used a couple of lazy quantifiers .*?, check out Laziness Instead of Greediness at this link if you would like to learn more: http://www.regular-expressions.info/repeat.html
What you're doing wrong is not using the MATLAB regexp function correctly. If you look under "Return Substrings using 'match' Keyword" on this site, you will see that the result you got is what is expected for what your code stated (it returns the parts of the input string that match the regular expression you supplied). I was going to post a suggestion, but someone beat me to it ;-). Good luck.

How do you concatenate strings in a Puppet .pp file?

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 '}'.