Ruby erb template 'or' operator - erb

I have a puppet manifest which uses an erb template.
This is the correct syntax according to the documentation, and it works perfectly.
<% if foo != bar %>
derp
<% else %>
herp
<% end %>
How can I combine the if statement with an 'or' operator?
Here are the following syntaxes that I have tried, however they return an error:
<% if foo != bar or if slurp != burp %>
derp
<% else %>
herp
<% end %>
Error: Could not run: /etc/puppet/modules/gitlab/templates/gitlab.yml.6-7-stable.erb:275: syntax error, unexpected $end, expecting keyword_end
; _erbout.force_encoding(__ENCODING__)
I tried changing <% to <%% since this is mentioned in the puppet docs.
<%% if foo != bar or if slurp != burp %%>
derp
<% else %>
herp
<% end %>
Error: Could not run: /etc/puppet/modules/gitlab/templates/gitlab.yml.6-7-stable.erb:241: syntax error, unexpected keyword_else, expecting $end
; else ; _erbout.concat "\n derp "
^
I've tried splitting the if-s
<% if foo != bar %> or <% if slurp != burp %>
derp
<% else %>
herp
<% end %>
Error: Could not run: /etc/puppet/modules/gitlab/templates/gitlab.yml.6-7-stable.erb:275: syntax error, unexpected $end, expecting keyword_end
; _erbout.force_encoding(__ENCODING__)
^

There is an extra if. The correct syntax is:
<% if foo != bar or slurp != burp %>
derp
<% else %>
herp
<% end %>
But your ones didn't work as your if-else construct was wrong. Read the documentation of if-else construct.

Ruby syntax for if/else blocks is:
if conditional
The conditional can include any logical operators such as 'or', 'and', '&', '|', '&&', '||'.
However, it can not contain another if block as your example has:
if foo != bar or if slurp != burp

ERB is Ruby1. ERB simply extracts the Ruby in the tags and the "inline text" into a mash-up of code and in-line string/output building to yield intermediate Ruby which is then executed.
As such, extracting the actual Ruby (as executed by ERB) looks like:
if foo != bar or if slurp != burp
# some inconsequential ERB magic to output "derp"
else
# some inconsequential ERB magic to output "herp"
end
Now, filling in the non-interesting parts with dummy expressions yields the following. (Ignore that the strings are always truthy-expressions; the problem is a Syntax Error.)
if "hello" or if "world"
else
end
And this yields the expected error message (see ideone demo).
prog.rb:3: syntax error, unexpected $end
Well .. why?
It's because there are two if-expressions2, but only one is closed and the code has been parsed as though grouping parenthesis have been added.
if "hello" or (if "world"
else
end) # <-- no `end` for `if "hello"`!
The fix is then simply to remove the nested if-expression.
# no extra `if` here, so only looking for one `end` below
if "hello" or "world"
else
end
1 A more correct statement would be that the code in ERB tags is Ruby, and ERB internally generates Ruby, using the content of ERB tags directly. This differs from other template engines which introduce their own syntax and parser. ERB is Ruby.
2 Ruby also supports the expr if expr (and if expr then .. end) forms. Regardless, the fundamental issue is the addition of the second unnecessary if.

Related

php strips [[:char_class:]] from the string

When concatenating mysql regex character classes in php they disappear from the resulting string i.e.:
$regexp_arr = array('(word1)', '(word2)');
$value = 'word3';
$regexp_str = implode('[[:space:]]', $regexp_arr);
$v1 = '[[:<:]](' . $value . ')';
echo $regexp_str;
// gives
'(word1)(word2)';
// instead of
'(word1)[[:space:]](word2)'
echo $v1;
// gives
'(word3)'
//instead of
'[[:<:]](word3)'
I've tried with double quotation marks ", the result still the same.
Is there a special way to concatenate this in php? Why are the '[[:char_class:]]' getting stripped?
server php version is 5.6.36
In MODX, [[ and ]] are special characters used to indicate they are tags MODX needs to process. Even when you echo or retrieve it from the database, MODX will process them when rendering.
For debugging, you can follow-up your echo with an exit().
echo $regexp_str;
exit();
That short-circuits MODX and gives you the actual value of the string including the square brackets.
If you want the value to be visible in a MODX-rendered resource or template, then you'll have to replace them with their html entities first:
$regexp_str = str_replace(['[',']'], ['[', ']'], $regexp_str);

Perl URL replace

I am trying to achieve following task,
Extract all urls from the text.
If domain belongs to white list, then replace them with modified urls.
Following is the code.
$text = '<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">';
$regex = '(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,#?^=%&:\/~+#-]*[\w#?^=%&\/~+#-])?';
#whiteList = ("www.amazon.de");
while ($text =~ /$regex/g) {
# regex result has following groups as matches
# $1 = scheme
# $2 = domain
# $3 = query parameters
# check if domain is in white list
if ( grep( /^$2$/, #whiteList ) ) {
# build new url
$new = "http://test.xyz.pqr/url=".$1."://".$2.$3;
# recreate old url
$old = $1."://".$2.$3;
# replace it here, but its not replacing
$text =~ s/$old/$new/g;
# but as an example replacing
# domain name with test, its working.
# it appears to be something to with back slash or forward
# slashes
$text =~ s/$2/test/g;
}
} print $text;
Any help or hint would be great. As I am new to perl programming.
I would use Regexp::Common in conjunction with Regexp::Common::URI to locate the URLs, and
URI to parse and transform them
Your very minimal data sample doesn't help, but here is a proof of my idea using that data
use strict;
use warnings 'all';
use Regexp::Common 'URI';
use URI;
use List::Util 'any';
use constant NEW_HOST => 'test.xyz.pqr';
my $text = <<'END';
<a href="http://www.amazon.de/Lenovo-Moto-Smartphone-Android-schwarz/dp/B01FLZC8ZI">
<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">
</a>
END
my #white_list = qw/ www.amazon.de /;
$text =~ s{ ( $RE{URI}{HTTP} ) } {
my $uri = URI->new($1);
my $host = $uri->host;
$uri->host(NEW_HOST) if any { $host eq $_ } #white_list;
$uri->as_string;
}exg;
print $text, "\n";
output
<a href="http://test.xyz.pqr/Lenovo-Moto-Smartphone-Android-schwarz/dp/B01FLZC8ZI">
<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">
</a>
The URL in $old contains characters that Perl's regex engine treats as part of the pattern, not as literal characters, when you use it inside the pattern match.
$text =~ s/$old/$new/g;
You need to escape those. You can do that with the \Q and \E commands.
$text =~ s/\Q$old\E/$new/g;
That should do the trick, assuming the rest of your code is working, which I have not tried.

how to parse html by sed - extract two strings delimited by two strings - on different lines, sequentially

I have a bash script:
v1='value="'
v2='" type'
do_parse_html_file() {
sed -n "s/.*${v1}//;s/${v2}.*//p" "${_SCRIPT_PATH}/IBlockListLists.html"|egrep '^http' >${_tmp_file}
}
... which is extracting from html file only URLs.
I would like to have on output:
somename URL
somename URL
--- example of the input html file is like the following:
</tr>
<tr class="alt01">
<td><b>iana-reserved</b></td>
<td>Bluetack</td>
<td><img style="border:0;" src="I-BlockList%20%7C%20Lists_files/star_4.png" alt="" height="15" width="75"></td>
<td><input style="width:200px; outline:none; border-style:solid; border-width:1px; border-color:#ccc;" id="bcoepfyewziejvcqyhqo" readonly="readonly" onclick="select_text('bcoepfyewziejvcqyhqo');" value="http://list.iblocklist.com/?list=bcoepfyewziejvcqyhqo&fileformat=p2p&archiveformat=gz" type="text"></td>
</tr>
<tr class="alt02">
<td><b>iana-private</b></td>
<td>Bluetack</td>
<td><img style="border:0;" src="I-BlockList%20%7C%20Lists_files/star_4.png" alt="" height="15" width="75"></td>
<td><input style="width:200px; outline:none; border-style:solid; border-width:1px; border-color:#ccc;" id="cslpybexmxyuacbyuvib" readonly="readonly" onclick="select_text('cslpybexmxyuacbyuvib');" value="http://list.iblocklist.com/?list=cslpybexmxyuacbyuvib&fileformat=p2p&archiveformat=gz" type="text"></td>
</tr>
--- result should be like following:
iana-reserved http://list.iblocklist.com/?list=bcoepfyewziejvcqyhqo&fileformat=p2p&archiveformat=gz
iana-private http://list.iblocklist.com/?list=cslpybexmxyuacbyuvib&fileformat=p2p&archiveformat=gz
---Is it possible to have it by sed on one line command ? If so, please help.
the first part of the list - the "somename" is always first than following by the URL sitting on the next /does not have to be second/ line.
>somename ... is delimited by 'href="URL">' and '</a>' on one line
>URL ... is always delimited by 'value="' and '" type' on any following line
thank you,
kind regards.
M.
With my cli html parser Xidel it is a single line:
xidel "${_SCRIPT_PATH}/IBlockListLists.html" -e '//a/concat(., " ", #href)'
shell is not the right tool to do this.
I can show you some scripts to do it in python or perl (ruby, java, php too) with a HTML parser. These are the right tools for this job.
This is the question maybe the most discussed on this web site, see this excellent post
One of that guys that makes this web site, wrote this too
Use a parser. There are many of them, here an example using HTML::TokeParser.
Content of script.pl:
#!/usr/bin/env perl
use warnings;
use strict;
use HTML::TokeParser;
my $p = HTML::TokeParser->new( shift ) || die;
while ( my $tag = $p->get_tag( 'a' ) ) {
printf qq|%s %s\n|, $p->get_text, $tag->[1]{href};
}
Run it like:
perl-5.14.2 script.pl htmlfile
That yields:
iana-reserved http://www.iblocklist.com/list.php?list=bcoepfyewziejvcqyhqo
iana-private http://www.iblocklist.com/list.php?list=cslpybexmxyuacbyuvib

Using Loops to Generate Dynamic Channel Field Names?

Having a bit of an issue generating channel fields based on a variable. Below is my attempt at a PHP solution:
{related_entries id="image_gallery"}
<?php for ($i = 1; $i <= 15; $i++) { ?>
{image_<?php echo $i; ?>}
<?php } ?>
{/related_entries}
Unfortunately ExpresssionEngine doesn't render these tags and just outputs them as:
{image_1} {image_2} {image_3}... etc.
I've tried some other looping plugins with no luck either, but I assume there is a plugin or method out there to help me.
Bonus question: Ideally, I will need a method that I can also check to see if the channel field actually has any data like: {if image_x}{image_x}{/if}
Make sure you have set PHP to parse on input in your template preferences. That should do the trick.

How to correctly quote a subpattern placeholder when passing it in a variable?

I am having a problem correctly quoting the subpattern placeholder '$1' when passing it to the replacement operator 's///' in a variable. Could someone shed some light on this and advise me, what I am doing wrong?
I am exporting as set of MS Word documents to HTML files. This works more or less OK except that the files contain many cross references and these need to be fixed to keep working.
The exported references are in the form 'href="../../somefilename.docx"' and these need to be changed into 'href="somefilename.htm"' to reference the exported html files instead of the original Word files.
An example file test.htm could e.g. look like:
<html>
<body>
<a href="../../filename1.docx" />
<a href="../../filename2.docx" />
<a href="../../filename3.docx" />
<a href="../../filename4.docx" />
</body>
</html>
and the program execution should then yield:
<html>
<body>
<a href="filename1.htm" />
<a href="filename2.htm" />
<a href="filename3.htm" />
<a href="filename4.htm" />
</body>
</html>
I wrote me a little Perl program 'ReplaceURLs' to do that job. It works fine, if I "hardcode" the pattern and the replacement expressions (i.e. if I place the pattern directly into the s/.../.../g statement) - see variant 1.
But to make it more flexible I would like to allow those expressions to be passed in as argument (i.e. s/$pattern/$subst/g) and this I can't get that working. I can pass in the pattern in a variable - see variant 2, but not the substition value containing the subpattern reference $1.
In variant 3 for some reason the $1 in the substitution value is not recognized as a subpattern marker but treated as a literal '$'.
#!/usr/bin/perl
$debug = TRUE;
$tgtfilename = $ARGV[0] || die("usage: ReplaceURLs.pl <filename> <url-pattern> <url-substvalue>");
$urlpattern = $ARGV[1] || "href=\"\.\./\.\./(.*)\.docx\""; # href="../../(filename).docx';
$urlsubstval = $ARGV[2] || "href=\"\$1.htm\""; # href="$1.htm" --> href="(filename).htm";
print "replacing all occurences of pattern '$urlpattern' in file '$tgtfilename' with '$urlsubstval':\n";
# open & read $tgtfilename
open($ifh, '<', $tgtfilename) || die "unable to open $tgtfilename for reading: $!";
#slurp = <$ifh>;
$oldstring = "#slurp";
close($ifh) || die "can't close file $tgtfilename: $!";
if ($debug) { print $oldstring,"\n"; }
# look for $urlpattern and replace it with $urlsubstval:
# variant 1: works
#($newstring = $oldstring) =~ s!href=\"\.\./\.\./(.*)\.docx\"!href=\"$1.htm\"!g;
# variant 2: works
#($newstring = $oldstring) =~ s!$urlpattern!href=\"$1.htm\"!g;
# variant : does not work - why?
($newstring = $oldstring) =~ s/$urlpattern/$urlsubstval/g;
# save file
#open($ofh, '>', $tgtfilename) || die "unable to re-open $tgtfilename for writing";
#print $ofh $newstring,"\n";
#close($ofh) || die "can't close file $tgtfilename: $!";
# done
if ($debug) { print "result of replacement:","\n", $newstring,"\n"; } else { print "done."; }
__END__
If I run this using "perl ReplaceURLs.pl test.htm" I always get:
<html>
<body>
<a href="$1.htm" />
<a href="$1.htm" />
<a href="$1.htm" />
<a href="$1.htm" />
</body>
</html>
instead of the desired result. How do I need to quote or escape the '$1' in $urlsubstval to get this working?
M.
See perlop.
Options are as with m// with the addition of the following replacement specific options:
e Evaluate the right side as an expression.
ee Evaluate the right side as a string then eval the result.
r Return substitution and leave the original string untouched.
So, rather obscurely,
$ ls -1 | perl -pE '$str = q{"--$1--"}; s/(hah)/$str/ee;'
The solution by bobbogo only works, if the $str does not contain anything interfering with Perl's syntax. But because I wanted the replacement to contain something that by accident happens to look like a Perl assignment, namely 'href="$1.htm"', this yielded warnings 'Unquoted string "href" may clash with future reserved word ...' as well as errors 'Use of uninitialized value in substitution iterator at ..." and then crashed.
So, my finally working solution was to instead construct the command using proper string substitution and then to eval(...) that constructed command:
#!/usr/bin/perl
$debug = 1;
$tgtfilename = $ARGV[0] || die("usage: ReplaceURLs.pl <filename> [ <url-pattern> [ <url-substvalue> ] ]");
$urlpattern = $ARGV[1] || 'href="\.\./\.\./(.*)\.docx"'; # href="../../<filename>.docx"" in regexp format
$urlreplace = $ARGV[2] || 'href="$1.htm"'; # href="$1.htm" --> href="<filename>.htm";
print "replacing all occurences of pattern '$urlpattern' in file '$tgtfilename' with '$urlreplace':\n";
# open & read $tgtfilename
open($ifh, '<', $tgtfilename) || die "unable to open $tgtfilename for reading: $!";
#slurp = <$ifh>;
$oldstring = "#slurp";
close($ifh) || die "can't close file $tgtfilename: $!";
if ($debug) { print $oldstring,"\n"; }
# construct command to look for $urlpattern and replace it with $urlreplace:
$newstring = $oldstring;
$cmd = '$newstring =~ s!'.$urlpattern.'!'.$urlreplace.'!g';
# execute it:
if ($debug) { print "cmd=", $cmd, "\n"; }
eval($cmd);
# done
if ($debug) {
print "result of replacement:","\n", $newstring,"\n";
} else {
# save to file:
open($ofh, '>', $tgtfilename) || die "unable to re-open $tgtfilename for writing";
print $ofh $newstring,"\n";
close($ofh) || die "can't close file $tgtfilename: $!";
print "done.";
}
__END__

Resources