how to remove the double quotes in output when i use echo command with "< >" (these charaters) in the string? - string

I wish to create a required no. of html divisions each with a different id (a series).
but when I write in a loop
echo "<div id=%prefix%%i%> %innerHTML% </div>" >> file.txt
It should be like
<div id=a1> x </div>
<div id=a2> x </div>
<div id=a3> x </div>
but it comes out to be
"<div id=a1> x </div>"
"<div id=a2> x </div>"
"<div id=a3> x </div>"
I have tried omitting the double quotes "" but then it throws an error due to the use of '>' (used to write in a file)
help me with this

An example as per Aacini's comment:
#Echo Off
Set "innerHTML=x"
Set "prefix=a"
(For /L %%A In (1 1 3) Do Set /P "=<div id=%prefix%%%A> %innerHTML% </div>"<Nul&Echo=)>"file.txt"
Pause

echo ^<escape them^>
this works absolutely fine.
echo ^<div id=%prefix%%i%^> %innerHTML% ^</div^> >> file.txt

Related

Can't get li text() from a line

echo '<script>var newUL = $("<ul>';
for($i=1;$i<=4;$i++)
{
echo "<li>"."abcd"."</li>";
}
echo '</ul>");';
echo "\n";
echo '$("#filemanager li").click(function(){$(this).append(newUL);});</script>';
echo '<script>$("#filemanager li").click(function(){alert($(this).text());}); </script>';
"#filemanager" is a div tag
I can't get text from one appended -li- ... it returns text of all appended -li-
By $("#filemanager li") command you've got a collection.
Try this:
$("#filemanager li").each(function(){
alert($(this).text())})

Batch: How to append the name of a variable instead of the value of that variable

I am trying to append strings to a text file. So far, my code looks like this:
echo -%appointment% >>C:\Users\Evan\Desktop\Programming\Events.txt
echo set /a h=(%hours%*3600)+(%minutes%*60) >>C:\Users\Evan\Desktop\Programming\Events.txt
echo set /a i=%day%-%dbf% >>C:\Users\Evan\Desktop\Programming\Events.txt
echo if %g% leq %h% if %b% equ %day% echo %appointment% %time% Today >>C:\Users\Evan\Desktop\Programming\Events.txt
echo if %b% lss %day% if %b% geq %i% echo %appointment% %time% %date% >>C:\Users\Evan\Desktop\Programming\Events.txt
The problem is, the variables %b% and %g% are dependent on the specific occurance. %b% and %g% change with date, so while their values will be accurate when I append them into the text file, their values will NOT be accurate when I actually want to convert the text file into a batch file and use it. How do I literally append the variable %b% as text and not its current value so that it can change every time I run the text file as a batch? If I try to append "%b%" in code with those quotations, in the occuring file, it is simply output as "".
Thank you.
Double the % for the % you wish to output literally.
% escapes % (ie causes it to be interpreted as an ordinary, not a special character.)
^ escapes most awkward characters like | - but not %

How to split string in a variable without loosing spaces?

how can i split the string
" This is a text with spaces "
that is in the variable "string"
into text parts without loosing the spaces ?
set string="# This is a text with spaces #"
should be split into
"# This"
" is"
" a"
" text"
" with"
" spaces #"
Using For /F "delims= " ... doesn't work because it eliminates all spaces.
Is there a 'simple' solution or can anyone explain how to parse the string character by character
so i can count up spaces to first character, then read all characters until next space and write
the counted spaces and the read characters together to a new/temp variable ??
thanks
Yeah, I don't really understand the # either. What is it about " spaces #" that makes it hold onto the trailing spaces, while all other elements keep the preceding but not the proceeding spaces?
Oh, well, effort spent in asking = effort spent in answering. Do with this what you will.
#if (#a==#b) #end /*
:: batch portion
#echo off
setlocal
call :split "# This is a text with spaces #"
exit /b
:split <string>
cscript /nologo /e:jscript "%~f0" "%~1"
goto :EOF
:: JScript portion */
WSH.Echo(WSH.Arguments(0).match(/\s*\S+/g).join('\n'));
Output:
#
This
is
a
text
with
spaces
#
Update
If you want the first + second, and the penultimate + ultimate elements joined, modify the JScript portion of the above script as follows:
:: JScript portion */
var m = WSH.Arguments(0).match(/\s*\S+/g);
m[0] = m.shift() + m[0];
m[m.length - 2] += m.pop();
WSH.Echo(m.join('\n'));
Output:
# This
is
a
text
with
spaces #
And if you want each element enclosed in quotation marks, change the last line as follows:
WSH.Echo('"' + m.join('"\n"') + '"');
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"
I don't see a simple solution in batch, though of course if you can consider powershell or javascript you'll be working with a more appropriate toolset for string manipulation.
Sticking with the batch requirement, you can loop through character by character and "collect" your words with something like this:
#echo off
setlocal enabledelayedexpansion
set "string= This is a text with spaces "
set idx=0
set "word="
set "char="
set "lastchar= "
:loop
if "!string:~%idx%!" equ "" goto :eof
set char=!string:~%idx%,1!
if "%char%" equ " " (
if "%lastchar%" neq " " (
echo [%word%]
set word=%char%
) else (
set word=%word%%char%
)
) else (
set word=%word%%char%
)
set lastchar=%char%
set /a idx=%idx%+1
goto loop
This script uses batch's substring feature !string:~%idx%,1 to grab a single character from the string, incrementing idx with each loop. Then it's just a matter of processing the word (echo in this example) when the previous character was not a space and the current one is.
This writes out:
[ This]
[ is]
[ a]
[ text]
[ with]
[ spaces]
Note that I'm ignoring the # you had in your example because I don't understand where they fit in.
the trick is substituting the contiguous spaces by just one space and the rest by some arbitrary character. Assuming your string does not contain #s and that there are no more than 9 contiguous spaces, you can try this
set st=%st: = ########%
set st=%st: = #######%
set st=%st: = ######%
set st=%st: = #####%
set st=%st: = ####%
set st=%st: = ###%
set st=%st: = ##%
set st=%st: = #%
then you may parse with for /f and substitute back your #s by spaces
setlocal enabledelayedexpansion
for /f %%a in ("%st%") do (
set ss= %%a
echo !ss:#= !
)
note that set inside the parentheses block requires you to enable delayed expansion and to use the ! syntax (see HELP SET)
But this technique will only extract the first substring. To generalize, you need another trick, that is substituting the spaces into newlines so that the for /f will loop kinda line by line
note that in order to obtain a newline char you need to preserve the two blank lines after the set command
set nl=^
rem continue two lines down....
for /f %%a in ("%st: =!nl!%") do (
set ss= %%a
set ss=!ss:#= !
echo [!ss!]
)
Try this:
#echo off &setlocal enabledelayedexpansion
set "string=# This is a text with spaces #"
set string1=%string%
for %%i in (%string%) do (
set string1=!string1: %%i = "%%i" !
set /a strings+=1
)
set string1=#"%string1:~1,-1%"#
set string1=%string1:"= "%
for %%i in (%string1%) do (
set /a count+=1
set string2=%%i
set string2=!string2: "=!
set string2=!string2:"=!
if !count! equ 2 (
set $s1=!$s1!!string2!
)else if !count! equ %strings% (
set /a count-=1
call set $s!count!=%%$s!count!%%!string2!
) else set $s!count!=!string2!
)
for /f "tokens=1*delims==" %%i in ('set "$s"') do echo "%%j"
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"
If I had to accomplish this obscure task, I would use a hybrid JScript/batch technique like in rojo's answer. However, I would use a REPL.BAT utility that I have already written. Assuming my REPL.BAT is in either the current folder, or else somewhere in the PATH, then the following will work:
#echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Build an "array" of text parts
set cnt=0
for /f delims^=^ eol^= %%A in ('repl "([^ ])(?= )" "$1\n" xs string') do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
But if I wanted a pure batch solution, I would use the fairly efficient method below:
#echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Define LF to contain a single line feed character (0x0A)
set LF=^
:: Above 2 blank lines are critical - DO NOT REMOVE
:: Insert a line feed before every space
for %%n in ("!LF!") do set "string=!string: =%%~n !"
:loop Remove line feeds sandwiched by spaces
for %%n in ("!LF!") do set "string2=!string: %%~n = !"
if "!string2!" neq "!string!" (
set "string=!string2!"
goto :loop
)
:: Build an "array" of text parts: FOR /F splits the string at line feeds
set /a cnt=0
for /f delims^=^ eol^= %%A in ("!string!") do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print out the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
Both solutions above give the following output:
string1=[#]
string2=[ This]
string3=[ is]
string4=[ a]
string5=[ text]
string6=[ with]
string7=[ spaces]
string8=[ #]
Note that the FOR loop %%A expansion will corrupt the results if the string contains ! due to delayed expansion. This limitation can be eliminated with additional coding. All the other posted solutions that use a FOR loop suffer from this same limitation. (at least they did when I wrote this)

Scripting for windows

This is my first time trying scripting and I'm trying to create a small program that does a simple division and mod in a loop, and then calculates the average of the mod results.
This is what I have tried in Linux .sh, but how could I make it compatible with Windows .bat? Your help is very appreciated.
echo "enter first number:"
read first_num
echo “enter second number:”
read second_num
while [ first_num && second_num != 999 ]
do
if [ second_num != 0 ]; then
echo "Enter first number:"
read first_num
echo"Enter second number:"
read second_num
echo first_num "/" second_num "=" $((first_num / second_ num)) >> file.txt
else
echo "ERROR. Cannot divide by 0. Enter another number:"
fi
done
if [ first_num == 999 || second_num == 999 ]; then
echo "You have exited the loop."
fi
#Mod 5 of numbers 1-100:
for i in {1...100}
do
result=$((i % 5))
echo i + "%5=" + result >> file.txt
done
#Average of results:
int sum=0
for (( i=1; i<101; i=i+1 ))
do
sum=sum+$((i % 5))
average=$((sum/100))
echo average
echo average >> file.txt
done
echo "enter first number:"
read first_num
becomes
set /p first_num="Enter first number "
while [ first_num && second_num != 999 ]
don't have a WHILE - have to wire it. Think clubs and rocks.
:loop
if %first_num%==999 goto endloop
if %second_num%==999 goto endloop
...
goto loop
:endloop
:name is a label, %var% retrieves contents of var - is always a string enclose in quotes if the string includes spaces.
if [ second_num != 0 ]; then
translated is
if NOT %second_num%==0 ( ...things... ) else (...other things...)
or, of course
if %second_num%==0 ( ...other things... ) else (...things...)
Quirk: (one of many) : the first open-parenthesis MUST occur on the same physical line as the IF and the ELSE must be on the same physical line as the ) of the on-true statemet sequence.
echo first_num "/" second_num "=" $((first_num / second_ num)) >> file.txt
Can't do a calculation in an echo
set /a result=(first_num / second_ num)
OR
set /a result=(%first_num% / %second_ num%)
SET /A applies the results of an arithmetic expression - later addition and more C-like semantics
then
echo %first_num% / %second_num% = %result% >> file.txt
purely stringing the elements together.
Next there is a small problem. During the parsing process, any %var% is replaced by its PARSE-TIME value and THEN the line is executed. Consequently, the ECHO line above would show the values as they stood when the IF statement was entered, not after the calculations.
Two cures:
You can use SETLOCAL ENABLEDELATEDEXPANSION to switch the interpreter mode. In DELAYEDEXPANSION mode, !var! may be used to retrieve the RUN-TIME value of var. A SETLOCAL is terminated by an ENDLOCAL or by reaching END-OF-FILE in the same context. Any environment changes after a SETLOCAL are undone by an ENDLOCAL which is why it's often performed immediately after the #echo off - keeps the environment clean.
second cure is to use a subroutine. CALL :SUB (the colon means 'internal subroutine - start label is in this batchfile'. Omitting it means 'this is an external executable') The CALL creates a new context, copying the then-existing environment variables, so
:sub
echo %first_num% / %second_num% = %result% >> file.txt
goto :eof
will display the variables from the environment as it stood when a CALL :SUB was executed.
Note that GOTO :EOF (the colon is REQUIRED means 'go to physical end-of-file' - the label EOF should not be declared...
(beware also flow-through to subroutines normally placed at the end of batchfiles. A judicious GOTO :EOF ensures that flow-through does not occur...
#Mod 5 of numbers 1-100:
The comments indicator is officially REM
rem Mod 5 of numbers 1-100:
BUT
::Mod 5 of numbers 1-100:
is often used as it's easier to type BUT since it's actually a misuse of a label, it is actually a label, and labels can't be used in a compound statement, you you can't use it within the parentheses of IF ... (...) else (...) or FOR...DO (...)
for i in {1...100}
becomes
for /L %%i in (1,1,100) do (
The metavariable %%i IS case-sensitive and a single character. in a FOR /L the elements are (start,step,end) - see FOR /? from the prompt (or generally command /? from the prompt) for docco...
result=$((i % 5))
becomes
set /a result=%%i %% 5
/a because the RHS is an arithmetic expression to be evaluated; %% 5 because % escapes %, the space is irrelevant and the processor needs to know that the MOD operator % is being used, not %5 (the fifth command-line argument)
int sum=0
No such thing as types; all environment variables are strings and only interpreted as integers by the set /a statement
so - that's about all there is to it...
Hope you're looking for this:
#echo off
setlocal enabledelayedexpansion
> file.txt type nul
:loopInput
echo enter first number:
set /p first_num=
echo enter second number:
set /p second_num=
if !first_num! neq 0 (
if !second_num! neq 999 (
if !second_num! equ 0 (
echo ERROR. Cannot divide by 0. Enter another number:
goto loopInput
)
goto loopDiv
)
)
goto :skipDiv
:loopDiv
set /a division=first_num/second_num
>> file.txt echo !first_num! / !second_num! = !division!
goto loopInput
:skipDiv
echo You have exited the div loop.
>> file.txt echo Mod 5 of numbers 1-100:
for /l %%a in (1,1,100) do (
set /a mod=%%a%%5
>> file.txt echo %%a %% 5 = !mod!
)
set sum=0
for /l %%a in (1,1,100) do (
set /a sum+=%%a%%5
)
set /a average=sum/100
>> file.txt echo Average of results: !average!

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