airvector
asked on
Dos Batch Scripting: value passing, format issue. Nice Points!
Hi, I have obtained a way to trim leading and trailing spaces in a string. The answer is below, in the code snippet. This script returns a string in all cases, even if the input is all spaces within quotes, where the script will return "".
Now there is an input that is problematic for me. Pass it " 12 "1" 23 "", and the function will fail. However, if you only run the logic for removing the leading spaces, the input works.
So you get points if:
1. you can explain to me why this is happening,
2. you can provide a solution to the failure in the trim trailing spaces segment,
3. you could make the input appear stripped of leading and trailing spaces as the output for the following batch script:
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp aces.bat %%a`) do echo %%s
)
Best of luck,
airvector
Now there is an input that is problematic for me. Pass it " 12 "1" 23 "", and the function will fail. However, if you only run the logic for removing the leading spaces, the input works.
So you get points if:
1. you can explain to me why this is happening,
2. you can provide a solution to the failure in the trim trailing spaces segment,
3. you could make the input appear stripped of leading and trailing spaces as the output for the following batch script:
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp
)
Best of luck,
airvector
set string=%~1
echo What it looks like before [%string%]
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
echo to trailing
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
:return
echo What it looks like afterwards [%string%]
echo "%string%"
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
airvector
check this out!!
Steve
I'm surprised you disn't SHIFT the parameters as in the following code:
@echo off
setlocal enabledelayedexpansion
echo.
echo You input:
echo.
:loop
set string=%~1
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
echo [%string%]
shift
if not "%~1"=="" goto loop
check this out!!
Steve
I'm surprised you disn't SHIFT the parameters as in the following code:
@echo off
setlocal enabledelayedexpansion
echo.
echo You input:
echo.
:loop
set string=%~1
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
echo [%string%]
shift
if not "%~1"=="" goto loop
Oh, btw, my output was:
.
.
C:\Batch\EE\25718465>getparams "hello" " test " "left edkejde " " 12 "1" 23
You input:
[hello]
[test]
[left edkejde]
[12 "1" 23]
Just removed a rogue double-quote character (see below) and got the ouput as indicated in the code window:
rogue
|
C:\Batch\EE\25718465>getpa rams "hello" " test " "left edkejde " " 12 "1" 23
.
.
rogue
|
C:\Batch\EE\25718465>getpa
.
.
C:\Batch\EE\25718465>getparams "hello" " test " "left edkejde " 12 "1" 23
You input:
[hello]
[test]
[left edkejde]
[12]
[1]
[23]
==> airvector
==> Now there is an input that is problematic for me. Pass it " 12 "1" 23 "", and the function will
==> fail. However, if you only run the logic for removing the leading spaces, the input works.
I'm confused. The string you show has 5 double quotes in it, that feels like an invalid string, I would think you at least always need an even number. Am I missing something?
~bp
==> Now there is an input that is problematic for me. Pass it " 12 "1" 23 "", and the function will
==> fail. However, if you only run the logic for removing the leading spaces, the input works.
I'm confused. The string you show has 5 double quotes in it, that feels like an invalid string, I would think you at least always need an even number. Am I missing something?
~bp
To make this code (your code from above) work:
@echo off
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp aces.bat %%a`) do echo %%s
)
You will need the following batch file (named: TrimLeadingAndTrailingSpac es.bat):
@echo off
set string=%~1
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
echo.%string%
@echo off
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp
)
You will need the following batch file (named: TrimLeadingAndTrailingSpac
@echo off
set string=%~1
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
echo.%string%
This is shorter:
To make this code (your code from above) work:
@echo off
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp aces.bat %%a`) do echo %%s
)
You will need the following batch file (named: TrimLeadingAndTrailingSpac es.bat):
@echo.%~1
Yep, just a single line of code !!!
NOTE: As before, note the use of the full stop character.
To make this code (your code from above) work:
@echo off
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSp
)
You will need the following batch file (named: TrimLeadingAndTrailingSpac
@echo.%~1
Yep, just a single line of code !!!
NOTE: As before, note the use of the full stop character.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
t0t0 - I couldnt get it to work reliably with his suggested string using a subroutine stripping the spaces, it always parsed into next token at the next ". Will have to give thes suggestions a go too, wasnt aware oh history of the question.
t0t0, that last one seems to split up the last entry into tokens for me:
C:\Utils\scripts>trim1 "hello" " test " "left edkejde " 12 "1" 23
hello
test
left edkejde
12
1
23
which may be the intention of course, nice technique though.
For the other technique I get this back:
C:\Utils\scripts>trim2 "hello" " test " "left edkejde " 12 "1" 23
hello
test
left edkejde
12
as the fourth parameter is split into %1 %2 etc. by the " " I guess?
C:\Utils\scripts>trim1 "hello" " test " "left edkejde " 12 "1" 23
hello
test
left edkejde
12
1
23
which may be the intention of course, nice technique though.
For the other technique I get this back:
C:\Utils\scripts>trim2 "hello" " test " "left edkejde " 12 "1" 23
hello
test
left edkejde
12
as the fourth parameter is split into %1 %2 etc. by the " " I guess?
ASKER
t0t0, I placed the single-line echo with full stop in a batch and ran it on the problem input. The output gave me
12 " "1" 23 "
which is fine on the right side, but the spaces on the left would have to be trimmed.
As for the other suggestions:
Dragon-it, using the exact same code as in OP, you didn't have any problems. On the other hand, I get the output you see at the bottom. And I get a similar problem using your code t0t0. However, again, in all code suggested, the input works if I remove the trailing segment. I can't figure out why.
As for the FOR loop code, I prefer testing it once I get the first batch code working. The purpose of the for loop in the second part of the qtn, keep in mind, will be used to run trimbla.bat on every item in the list output of another command (For lack of piping). I used ~1 ~2 ~3 ~4 to simplify my test.
12 " "1" 23 "
which is fine on the right side, but the spaces on the left would have to be trimmed.
As for the other suggestions:
Dragon-it, using the exact same code as in OP, you didn't have any problems. On the other hand, I get the output you see at the bottom. And I get a similar problem using your code t0t0. However, again, in all code suggested, the input works if I remove the trailing segment. I can't figure out why.
As for the FOR loop code, I prefer testing it once I get the first batch code working. The purpose of the for loop in the second part of the qtn, keep in mind, will be used to run trimbla.bat on every item in the list output of another command (For lack of piping). I used ~1 ~2 ~3 ~4 to simplify my test.
prompt> TrimLeadingAndTrailingSpaces.bat " 12 "1" 23 ""
What it looks like before [ 12 "1" 23 "]
to trailing
" ( was unexpected at this time.
So how do you want the script to handle uneven number of quotes. Because you have 5 quotes in your example the input is taken as 1 parameter.
AT,
Right, that was my question which is still unanswered...
~bp
Right, that was my question which is still unanswered...
~bp
ASKER
I want the input to be taken as 1 parameter, and echoed once as output.
Input: [" 12 "1" 23 ""]
output ["12 "1" 23 ""]
ASKER
This output is also ok, I'll just add quotes afterwards.
Output: [12 "1" 23 "]
Double check there are no trailing spaces on any of the lines in the original script, especially copying from here you get them, I know I did from your script post above. Just passing keyboard, will look later.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I think the reason your original script doesn't work it because the command interpretter treats double quotes somewhat special, and especially pairs of double quotes. As a result a simple statmment like
if "A"=="A" echo EQUAL
will work, but the following fails
if ""A"==""A" echo EQUAL
so if in a statement like
if "%var1%"=="%var2%" echo EQUAL
if either var has just a leading or trailing quote then the statement will fail.
By using delayed variable expansion, the interpretter doesn't actually see the value of the vars until it's actually time to execute the statement (not "parse" it), and so treats it differently, not seeing the pairs of double quotes on the input line.
Sorry, kind of a vague explanation but a hard topic to simplify.
~bp
if "A"=="A" echo EQUAL
will work, but the following fails
if ""A"==""A" echo EQUAL
so if in a statement like
if "%var1%"=="%var2%" echo EQUAL
if either var has just a leading or trailing quote then the statement will fail.
By using delayed variable expansion, the interpretter doesn't actually see the value of the vars until it's actually time to execute the statement (not "parse" it), and so treats it differently, not seeing the pairs of double quotes on the input line.
Sorry, kind of a vague explanation but a hard topic to simplify.
~bp
ASKER
Well, using part of t0t0's code and billprew's code, I came up with what you see below. The first part of the answer done.
@echo off
setlocal EnableDelayedExpansion
set string=%*
echo What it looks like before [%string%]
if not defined string (
goto :end
)
if ^%string:~0,1%==^" (
if ^%string:~-1%==^" (
set string=%string:~1,-1%
)
)
:leading
if "!string:~0,1!" == " " (
set string=!string:~1!
goto leading
)
echo to trailing
:trailing
if "!string:~-1!" == " " (
set string=!string:~0,-1!
goto trailing
)
:return
echo What it looks like afterwards ["!string!"]
echo "!string!"
ASKER
Now the FOR loop. The script, the call, the output:
*******************
File: ForLoop.bat
*******************
@echo off
SETLOCAL EnableDelayedExpansion
FOR %%a IN ("%~1", "%~2", "%~3", "%~4") DO (
for /F "usebackq delims=" %%s in (`TrimLeadingAndTrailingSpaces.bat %%a`) do echo %%s
)
**********************
Output with @echo off
**********************
Prompt> ForLoop.bat " 12 "1" 23 ""
%s
%s
%s
*************************
Output without @echo off
*************************
Prompt> ForLoop.bat " 12 "1" 23 ""
Prompt> SETLOCAL EnableDelayedExpansion
Prompt> FOR %a IN (" 12 "1" 23 "", "", "", "") DO ( for /F "usebackq delims=" %s in (`trim.bat %a`) do echo %s
Prompt> echo %s
%s
Prompt> echo %s
%s
Prompt> echo %s
%s
Prompt>
Prompt>
ASKER
sorry for the name mismatch: above: trim.bat is actually TrimLeadingAndTrailingSpac es.bat
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Also, I dislike aborting programs in this manner
Well, I'm more of the type that I don't like making code halt if there's an error. I prefer things continue, but with proper handling (like exception handling in javascript). So, I've adjusted my code to return "" if not defined, adding the line
if not defined string goto :end code
as you suggested. However, I replaced all jump to :end as jumps to :returnSo, the FOR loop is to go through the output in list form of another command. This command outputs strings, so it could be anything you like, filenames, names, dates. However, the output values are excepted in any shape (quoted, not quoted, odd quotes, double-quotes, quoted with quotes with spaces inside, you name it).
Examples:
"12345"
" 12345 "
12345
"12"345"
" 12 " 345 "
12 " 345
12 " 345 "
" 12 " 345
""
"" 12 " 345 "
12 " " 345
" 12 " " 345
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
So your example above would the afterwards look like this?
Or something close?
Or something close?
"12345"
"12345"
"12345"
"12"345"
"12 " 345"
"12 " 345"
"12 " 345 ""
""12 " 345"
""
"" 12 " 345"
"12 " " 345"
"12 " " 345"
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
My output looks like this:
What it looks like before [12345]
What it looks like afterwards [12345]
"12345"
What it looks like before [ 12345 ]
What it looks like afterwards [12345]
"12345"
What it looks like before [12345]
What it looks like afterwards [12345]
"12345"
What it looks like before [12"345]
What it looks like afterwards [12"345]
"12"345"
What it looks like before [ 12 " 345 ]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [12 " 345]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [12 " 345 ]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [ 12 " 345]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before []
What it looks like afterwards []
""
What it looks like before [" 12 " 345 ]
What it looks like afterwards [" 12 " 345]
"" 12 " 345"
What it looks like before [12 " " 345]
What it looks like afterwards [12 " " 345]
"12 " " 345"
What it looks like before [ 12 " " 345]
What it looks like afterwards [12 " " 345]
"12 " " 345"
What it looks like before [12345]
What it looks like afterwards [12345]
"12345"
What it looks like before [ 12345 ]
What it looks like afterwards [12345]
"12345"
What it looks like before [12345]
What it looks like afterwards [12345]
"12345"
What it looks like before [12"345]
What it looks like afterwards [12"345]
"12"345"
What it looks like before [ 12 " 345 ]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [12 " 345]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [12 " 345 ]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before [ 12 " 345]
What it looks like afterwards [12 " 345]
"12 " 345"
What it looks like before []
What it looks like afterwards []
""
What it looks like before [" 12 " 345 ]
What it looks like afterwards [" 12 " 345]
"" 12 " 345"
What it looks like before [12 " " 345]
What it looks like afterwards [12 " " 345]
"12 " " 345"
What it looks like before [ 12 " " 345]
What it looks like afterwards [12 " " 345]
"12 " " 345"
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Perhaps UNCONFIRMED is a better choice of label rather than UNKNOWN.... but I hope you know what I mean...
airvector
I am still waiting for a reply to my comment (29959974)
I am still waiting for a reply to my comment (29959974)
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
AmazingTech
Nice to see you contribute to this question.
Hopefully you'll agree to the contents of my previous comment and seek to apply some of the information there to your treatment of the samples you've already commented on.
Taking into consideration the oder of parsing from left-to-right (as described above), what impact would this have on the results from the test data you used?
Would you agree this is the best approach?
Btw, in your code:
if [^%string:~0,1%] == [^"]....
It is not necessary to use square-brackets if we test for a nul string beforehand. And the spaces around the equality sign '==' could be risky in some situation (I seem to remember from some time ago).
Nice to see you contribute to this question.
Hopefully you'll agree to the contents of my previous comment and seek to apply some of the information there to your treatment of the samples you've already commented on.
Taking into consideration the oder of parsing from left-to-right (as described above), what impact would this have on the results from the test data you used?
Would you agree this is the best approach?
Btw, in your code:
if [^%string:~0,1%] == [^"]....
It is not necessary to use square-brackets if we test for a nul string beforehand. And the spaces around the equality sign '==' could be risky in some situation (I seem to remember from some time ago).
ASKER
Guys, I don't know what to say... Plainly, I have a command that echoes many values, and these values have quotes at f'ed up places. I want to go through these values, and all I've been given to date is a FOR loop to use. No one knows how to pipe here, so I'm using a FOR loop, ok?
Now, I want to work on each value using the TrimLeadingAndTrailingSpac es.bat . That's why the batch file looks like what you see in the OP.
I'll provide more details briefly.
Now, I want to work on each value using the TrimLeadingAndTrailingSpac
I'll provide more details briefly.
ASKER
So, as promised, the answers to t0t0's qtns.
are you always only expecting FOUR items to be passed as parameters?
- This I've already answered (ID: 29938529). It can be a variable-sized list of items, obtained from another command that echoes many values. Added precision here, the values can contain any type of characters, most notably spaces and quotes, along with numerical AND alphabetical values, and any other bell or carriage character you can think of.
where are these items coming from? ie, user input? read from a file? piped from another process? etc, etc...
From User Input -No
Read from a file -Maybe, is STDOUT considered a file?
piped from another process -Maybe. If catching a series of echoes from STDOUT is considered piping, but I don't think so...
etc, -Idk
etc.... -Not sure, you?
People,
To make things simple... maybe... assume a batch file that echoes hex numbers from 1010 to 1020, placing quotes and spaces at random places. Let's call it wackyhex.bat for fun. The result is a string of alphanumericals, spaces and quotes echoed to STDOUT.
idk,
10"10
" 101"1
"1012 ""
...
101A"
1"01B "
...
"10"2" 0
Whatever, it's just an example...
Now, use a FOR loop to catch every echo from wackyhex.bat, and trim the leading and ending spaces using TrimLeadingAndTrailingSpac es.bat.
Does that make it simpler to understand? I was only using parameters to simplify my tests, like I've already described in ID: 29938529.
so far, your examples in your last comment suggest ONLY INTEGER values....
-But alas, to me it does not matter. It can be integers, characters. So long as you consider quotes and spaces differently from anything else, I'm content. Why? Because the quotes and spaces are the ones giving me problems. It's a DOS thing, you get that.
And what format will the output from 'that' command be?
-Please see example in ID: 29958928 and examples above.
are you always only expecting FOUR items to be passed as parameters?
- This I've already answered (ID: 29938529). It can be a variable-sized list of items, obtained from another command that echoes many values. Added precision here, the values can contain any type of characters, most notably spaces and quotes, along with numerical AND alphabetical values, and any other bell or carriage character you can think of.
where are these items coming from? ie, user input? read from a file? piped from another process? etc, etc...
From User Input -No
Read from a file -Maybe, is STDOUT considered a file?
piped from another process -Maybe. If catching a series of echoes from STDOUT is considered piping, but I don't think so...
etc, -Idk
etc.... -Not sure, you?
People,
To make things simple... maybe... assume a batch file that echoes hex numbers from 1010 to 1020, placing quotes and spaces at random places. Let's call it wackyhex.bat for fun. The result is a string of alphanumericals, spaces and quotes echoed to STDOUT.
idk,
10"10
" 101"1
"1012 ""
...
101A"
1"01B "
...
"10"2" 0
Whatever, it's just an example...
Now, use a FOR loop to catch every echo from wackyhex.bat, and trim the leading and ending spaces using TrimLeadingAndTrailingSpac
Does that make it simpler to understand? I was only using parameters to simplify my tests, like I've already described in ID: 29938529.
so far, your examples in your last comment suggest ONLY INTEGER values....
-But alas, to me it does not matter. It can be integers, characters. So long as you consider quotes and spaces differently from anything else, I'm content. Why? Because the quotes and spaces are the ones giving me problems. It's a DOS thing, you get that.
And what format will the output from 'that' command be?
-Please see example in ID: 29958928 and examples above.
Does ID: 29985617 work for you?
ASKER
AT, it most definitely works. Haven't tried the for loop part yet. So, I've combined your code with t0t0's code, and I got what you see attached. Qtn, how did you reduce this
:leadingif "!string:~0,1!" == " " ( set string=!string:~1! goto leading) echo to trailing :trailingif "!string:~-1!" == " " ( set string=!string:~0,-1! goto trailing)
-------------------------- ---------- ---------- --
To this:
-------------------------- ---------- ---------- ---
CALL :TRIM %string% GOTO :EOF :TRIM set string=%*
:leadingif "!string:~0,1!" == " " ( set string=!string:~1! goto leading) echo to trailing :trailingif "!string:~-1!" == " " ( set string=!string:~0,-1! goto trailing)
--------------------------
To this:
--------------------------
CALL :TRIM %string% GOTO :EOF :TRIM set string=%*
ASKER
Sorry, code for prev post attached here. (Rich text thing made the attachment dissappear)
@ECHO off
set string=%*
echo What it looks like before [%string%]
if not defined string goto :return
if ^%string:~0,1%==^" if ^%string:~-1%==^" set string=%string:~1,-1%
if not defined string goto :return
CALL :TRIM %string%
GOTO :EOF
:TRIM
set string=%*
:RETURN
echo What it looks like afterwards [%string%]
echo "%string%"
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Actually, I wouldn't do it this way. This only fixes the quotes if beginning and ending. You example input
" 12 " " 345
Would not remove the first quotes thus not triming the space before 12 unless that's what you wanted.
if ^%string:~0,1%==^" set string=%string:~1%
if ^%string:~-1%==^" set string=%string:~0,-1%
Which is essentially the same as mine with the brackets. I used the bracket for ease of understanding.
" 12 " " 345
Would not remove the first quotes thus not triming the space before 12 unless that's what you wanted.
if ^%string:~0,1%==^" set string=%string:~1%
if ^%string:~-1%==^" set string=%string:~0,-1%
Which is essentially the same as mine with the brackets. I used the bracket for ease of understanding.
This thread sure has wandered around a bit, and covered a lot of ground...
If you are also going to include other special characters like |, <, >, ^, etc in your input strings I think you will find that parsing and manipulating these in a BAT file will be a challenge. You also mention "bell and carraige" characters which to me imply "binary" characters, like a line feed, or a tab. These will also be particularly problematic in a BAT file.
I would post further since I believe I had a good bit of the solution in 29950728 but it still isn't quite clear to me exactly what the comain of input is, and what the needed output of the "parsing" and "trimming" needs to be. But I may be slower than most...
~bp
~bp
If you are also going to include other special characters like |, <, >, ^, etc in your input strings I think you will find that parsing and manipulating these in a BAT file will be a challenge. You also mention "bell and carraige" characters which to me imply "binary" characters, like a line feed, or a tab. These will also be particularly problematic in a BAT file.
I would post further since I believe I had a good bit of the solution in 29950728 but it still isn't quite clear to me exactly what the comain of input is, and what the needed output of the "parsing" and "trimming" needs to be. But I may be slower than most...
~bp
~bp
ASKER
billprew, I don't think it's a qtn of being slow, it seems to me that this has turned out to be alot more challenging that it first appeared, not only to solve, but also to understand. The question is so open and the vast scenarios that may exist bears the question of whether it is even plausible to be handled in BAT files, as you suggested. Though the "bell and carriage" characters thing was a pun, I think you got the gist of it.
You know, the idea is that I'm trying to get around the behavior of DOS, whereby it'll fail at a quote mismatch or at the appearance of an unexpected character. Take the backquote for example. What if my string contains quotes and a backquote, and it is passed to a call inside a for loop. I tried it, and it just doesn't run the script. I'll provide the example if you guys want it.
t0t0, as you said,
this is NOT a competition. We are experts who (in my case) enjoy solving problems using batch programming.
I for one have enjoyed the complexity and insight of this thread. (It's no wonder the replies keep popping in, I can barely keep up). Just remember that the onus will be on me at the end to properly assign points to those who've helped. For now, the TrimLeadingAndTrailingSpac es.bat script I came up with in ID: 30042968 was contributed by t0t0, billprew and AmazingTech, for now.
As for the FOR loop issue, I think I'll accept the solutions of those who've helped me come to a satisfying understanding of how DOS struggles with awkward values, what the problematic scenarios are (generally), and why the code in the OP fails, given the new version of TrimLeadingAndTrailingSpac es.bat . So, I suggest we continue where t0t0 left off on ID: 29990787. I personally am getting through ID: 30001694 as it is.
You know, the idea is that I'm trying to get around the behavior of DOS, whereby it'll fail at a quote mismatch or at the appearance of an unexpected character. Take the backquote for example. What if my string contains quotes and a backquote, and it is passed to a call inside a for loop. I tried it, and it just doesn't run the script. I'll provide the example if you guys want it.
t0t0, as you said,
this is NOT a competition. We are experts who (in my case) enjoy solving problems using batch programming.
I for one have enjoyed the complexity and insight of this thread. (It's no wonder the replies keep popping in, I can barely keep up). Just remember that the onus will be on me at the end to properly assign points to those who've helped. For now, the TrimLeadingAndTrailingSpac
As for the FOR loop issue, I think I'll accept the solutions of those who've helped me come to a satisfying understanding of how DOS struggles with awkward values, what the problematic scenarios are (generally), and why the code in the OP fails, given the new version of TrimLeadingAndTrailingSpac
ASKER
And, don't forget to REM the debug lines in TrimLeadingAndTrailingSpac es.bat when testing against the FOR loop. Just echo one output, that is, "%string%", at the end.
airvector
PLEASE READ THE FOLLOWING COMMENT VERY CAREFULLY.
UNLESS you can answer the following question satisfatorily, I will decline to contribute further to this thread.
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ------
QUESTION
In your opening statement, you write:
...there is an input that is problematic for me.
Pass it " 12 "1" 23 "", and the function will fail.
The function you refer to is TrimLeadingAndTrailingSpac es.bat.
Therefore, given the following command tail
" 12 "1" 23 ""
(Now, please think about this one VERY CAREFULLY!) Imagine for a moment it was YOU who had entered this as input on the command line. Looking back at this input now and realising you had made a mistake, WHAT SHOULD have entered instead (or in other word, WHAT did you INTEND to enter)?
The following is an example of how you might answer this question. You might reply with something along the following lines:
I INTENDED to enter:
the number 12 in double-quotes followed by,
"1" as it appears followed by,
the number 23 followed by,
a null (empty) string (denoted by "")
Of course, that's just ONE of many plausible interpretations....
I want to know what YOUR interpretation is of the command tail is based on what you might of INTENDED to enter had it been you who had entered it in the first place.
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ------
NOW, PLEASE ANSWER THE QUESTION
PLEASE READ THE FOLLOWING COMMENT VERY CAREFULLY.
UNLESS you can answer the following question satisfatorily, I will decline to contribute further to this thread.
--------------------------
QUESTION
In your opening statement, you write:
...there is an input that is problematic for me.
Pass it " 12 "1" 23 "", and the function will fail.
The function you refer to is TrimLeadingAndTrailingSpac
Therefore, given the following command tail
" 12 "1" 23 ""
(Now, please think about this one VERY CAREFULLY!) Imagine for a moment it was YOU who had entered this as input on the command line. Looking back at this input now and realising you had made a mistake, WHAT SHOULD have entered instead (or in other word, WHAT did you INTEND to enter)?
The following is an example of how you might answer this question. You might reply with something along the following lines:
I INTENDED to enter:
the number 12 in double-quotes followed by,
"1" as it appears followed by,
the number 23 followed by,
a null (empty) string (denoted by "")
Of course, that's just ONE of many plausible interpretations....
I want to know what YOUR interpretation is of the command tail is based on what you might of INTENDED to enter had it been you who had entered it in the first place.
--------------------------
NOW, PLEASE ANSWER THE QUESTION
ASKER
Two words: COPY, PASTE, was my initial answer.
But I gave your comment a little more thought, and I think it was the right thing to do. May I reword your question?
What do you expect someone careful to enter?
The answer is, and always has been: anything. I don't expect the user to be careful, and the user may not even be human. It may be some other batch file that reads every line from a file and calls TrimLeadingAndTrailingSpac es.bat on each line.
I know this may seem ludicrous: why trim spaces on something that's already f'ed up? But the point of using TrimLeadingAndTrailingSpac es.bat rather than anything else, is because it was one of the best scripts I had to handle tricky input (I spent 500 points on it alone already). I may want to do more complex operations on each line in the future, such as search for a specific pattern, but I wanted to start with something simple. Go figure!
Now I hope you understand where I'm coming from.
But I gave your comment a little more thought, and I think it was the right thing to do. May I reword your question?
What do you expect someone careful to enter?
The answer is, and always has been: anything. I don't expect the user to be careful, and the user may not even be human. It may be some other batch file that reads every line from a file and calls TrimLeadingAndTrailingSpac
I know this may seem ludicrous: why trim spaces on something that's already f'ed up? But the point of using TrimLeadingAndTrailingSpac
Now I hope you understand where I'm coming from.
It's a valid question and takes some investigation and understanding of what is going on. At the onset I'm sure it looked as though it was an easy request.
But upon numerous examinations by various experts it was difficult to figure out the true intended output.
Sorry, I don't usually put much detail/comments in the code I'm writing simply because I usually start from scratch for each question. This helps me in remembering the correct syntax. Also why bother with all the comments if the code does not satisfy the question being asked. I'm more than happy to explain what's going on or what I did or why I've done certain things after.
I hope you have arrived at a solution. Let us know if you need any more explaination.
In the end the tricky part of this question was the miss match number of double quotes and how it is handled at input parameters and how for loop fails. Using labels and %* we get around these 2 problems.
But upon numerous examinations by various experts it was difficult to figure out the true intended output.
Sorry, I don't usually put much detail/comments in the code I'm writing simply because I usually start from scratch for each question. This helps me in remembering the correct syntax. Also why bother with all the comments if the code does not satisfy the question being asked. I'm more than happy to explain what's going on or what I did or why I've done certain things after.
I hope you have arrived at a solution. Let us know if you need any more explaination.
In the end the tricky part of this question was the miss match number of double quotes and how it is handled at input parameters and how for loop fails. Using labels and %* we get around these 2 problems.
ASKER
As a sample script to run the for loop on, you can use this:
@echo off
echo hello my name is "John". I want to use function `dir /b` sometime in the future.
echo.
echo hi! My name is not ^, it's " Jane ". I have a question about using " " or "" in dos.
echo I want to ask it to the people on E-E, but
echo... with all these wierd characters like !@#$%^&*()[]éà / and ding dong! I don't know if I'll ever be able to
echo what I wanted to do in the first place. " -- 'Jane
ASKER
Call that code in ID 30136426 story.bat and run it in the following code. I can't make it simpler than that I'm afraid. Simple than what you see below and the question doesn't exist anymore, sorry.
@echo off
FOR /F "usebackq" %%a IN (`story.bat`) DO echo %%a
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ok, now we're getting somewhere.
ID: 30137629 works better than ID: 30136870 with a single FOR loop. Now let's try
ID: 30137629 works better than ID: 30136870 with a single FOR loop. Now let's try
@echo off
FOR /F "usebackq tokens=*" %%a IN (`story.bat`) DO (
echo story.bat: %%a
for /F "usebackq tokens=*" %%s in (`AMCore.TrimLeadingAndTrailingSpaces.callscript.bat %%a`) do echo trim.bat: %%s
)
ASKER
I get this. I think we're almost there!
story.bat: hello my name is "John". I want to use function `dir /b` sometime in t
he future.
trim.bat: "hello my name is "John". I want to use function `dir /b` sometime in t
he future."
story.bat: hi! My name is not , it's " Jane ". I have a question about using " "
or "" in dos.
trim.bat: "hi! My name is not , it's " Jane ". I have a question about using " "
or "" in dos."
story.bat: I want to ask it to the people on E-E, but
trim.bat: "I want to ask it to the people on E-E, but"
story.bat: .. with all these wierd characters like !@#$&*()[]Ta / and ding dong!
I don't know if I'll ever be able to do
'*' is not recognized as an internal or external command,
operable program or batch file.
trim.bat: ".. with all these wierd characters like !@#$"
story.bat: what I wanted to do in the first place. " -- 'Jane
trim.bat: "what I wanted to do in the first place. " -- 'Jane"
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I moved the &, and placed it between ding and dong in case the * had anything to do with it. I now get.
'dong!' is not recognized as an internal or external command,
operable program or batch file.
story.bat: hello my name is "John". I want to use function `dir /b` sometime in t
he future.
trim.bat: ""hello my name is "John". I want to use function `dir /b` sometime in
the future.""
story.bat: hi! My name is not , it's " Jane ". I have a question about using " "
or "" in dos.
trim.bat: ""hi! My name is not , it's " Jane ". I have a question about using " "
or "" in dos.""
story.bat: I want to ask it to the people on E-E, but
trim.bat: ""I want to ask it to the people on E-E, but""
story.bat: .. with all these wierd characters like !@#$*()[]Ta / and ding
trim.bat: "".. with all these wierd characters like !@#$*()[]Ta / and ding ""
story.bat: what I wanted to do in the first place. " -- 'Jane
trim.bat: ""what I wanted to do in the first place. " -- 'Jane""
ASKER
Above, I also did what was said in ID: 30139593, replaced %%a to "%%~a" in call to trimbla.bat.
ASKER
On escape characters:
http://www.robvanderwoude.com/escapechars.php
http://www.robvanderwoude.com/escapechars.php
ASKER
Finally having taken the time to read ID: 30001694.
The well designed example was
00000001 "John Doe ab123456c "Birmingham City"
certainly, if we're passing data like "John Doe" or "Birmingham City" then we do need to delimit them using double-quotes. In this simplified (and deliberately chosen data items) it wouldn't be too difficullt to match the proper tokens to their respective data fields using minimal logic.
simply adding a double-quote onto the end of this command tail would serve no useful purpose whatsoever.
True. It could be decided in advanced how long a column is, and ensure proper escaping or quote-matching within that size. For example, I could handle this as follows:
The well designed example was
00000001 "John Doe ab123456c "Birmingham City"
certainly, if we're passing data like "John Doe" or "Birmingham City" then we do need to delimit them using double-quotes. In this simplified (and deliberately chosen data items) it wouldn't be too difficullt to match the proper tokens to their respective data fields using minimal logic.
simply adding a double-quote onto the end of this command tail would serve no useful purpose whatsoever.
True. It could be decided in advanced how long a column is, and ensure proper escaping or quote-matching within that size. For example, I could handle this as follows:
0 1 2 3 4 5 6 7 8
01234567890123456789012345678901234567890123456789001234567890123456789001234567890
00000001 "John Doe " ab123456c "Birmingham City"
ASKER
Now, what if a user submits
00000001 John "J" Doe ab123456c "Birmingham City"
How would you handle that when expecting 4 values? Maybe apply the size rule again like this?.
00000001 John "J" Doe ab123456c "Birmingham City"
How would you handle that when expecting 4 values? Maybe apply the size rule again like this?.
0 1 2 3 4 5 6 7 8
01234567890123456789012345678901234567890123456789001234567890123456789001234567890
00000001 "John "J" Doe " ab123456c "Birmingham City"
ASKER
Keep in mind that the rabbit trail I've been following since ID: 30141572 is in response to ID: 30001694 for the sake of understanding and discussion. It is a case where we expect 4 values.
But for the sake of solving the problem in OP, please continue on the trail started as of ID: 30137629.
But for the sake of solving the problem in OP, please continue on the trail started as of ID: 30137629.
ASKER
Goal: escaping the ampersands
Let's say I create a batch file to escape every '&' in a string echoed to STDOUT. I would call that file escapeAmpersands.bat.
Calling it within a FOR loop seems to be a catch 22.
@echo off
FOR /F "usebackq tokens=*" %%a IN (`story.bat`) DO (
echo story.bat: %%a
for /F "usebackq tokens=*" %%s in (`escapeAmpersands.bat %%~a`) do echo escapeAmpersands.bat: %%s
)
Anyway, I created a batch to count ampersands based on the count quotes from ID: 30001694. It works when I call it off the command line, but not in the FOR loop, probably due to what AmazingTech described.
Let's say I create a batch file to escape every '&' in a string echoed to STDOUT. I would call that file escapeAmpersands.bat.
Calling it within a FOR loop seems to be a catch 22.
@echo off
FOR /F "usebackq tokens=*" %%a IN (`story.bat`) DO (
echo story.bat: %%a
for /F "usebackq tokens=*" %%s in (`escapeAmpersands.bat %%~a`) do echo escapeAmpersands.bat: %%s
)
Anyway, I created a batch to count ampersands based on the count quotes from ID: 30001694. It works when I call it off the command line, but not in the FOR loop, probably due to what AmazingTech described.
@echo off
setlocal enabledelayedexpansion
set string=%*
::-------------------------------
:: Get length of string
:: Count ampers
::-------------------------------
set ptr=0
set ampers=0
:loop
if "!string:~%ptr%,1!"=="" (
goto :end-loop
)
set character=!string:~%ptr%,1!
if ^%character%==^& (
set /a ampers+=1
)
set /a ptr+=1
goto :loop
:end-loop
set length=%ptr%
echo.
echo length %length%
echo ampers %ampers%
exit /b
ASKER
Has anyone heard of sed for windows?
The one thing I don't like about it is that it follows the GPL. I mean, I support the GPL, but when you want to have things that belong to you, it's less cool.
I'm starting to thing of doing this stuff in another language like ruby or python and making a call to the executable for output. I'm currently using grep, and the guys were able to make it a pipeable command.
Here is a sample line of code from one of my files:
The one thing I don't like about it is that it follows the GPL. I mean, I support the GPL, but when you want to have things that belong to you, it's less cool.
I'm starting to thing of doing this stuff in another language like ruby or python and making a call to the executable for output. I'm currently using grep, and the guys were able to make it a pipeable command.
Here is a sample line of code from one of my files:
for /F "usebackq" %%m IN (`echo %dSwtVal% ^| grep -E -o -i "^[[:space:]]*(left)|(right)[[:space:]]*$" ^| grep -E -o -i "(left)|(right)"`) do SET %dSwtVal%=%%m
I think there is SED for windows it's been a long time but I haven't used it. Working with the ampersand is troublesome in DOS. I've been trying to make things work but you might want to change the trim back to what t0t0 suggested if the ampersand is going to be used.
You can escape the ampersand with
Set string=%string:&=^&%
You can escape the ampersand with
Set string=%string:&=^&%
ASKER
For those still interested,
I'm working on the second part of the question on my end. I will post when I have sufficiently understood the way DOS deals with arguments in Call statements, For loop commands and regular batch calls, as well as the various contexts (calling from prompt or calling from within another script), and the various ways of getting argument values (getting all characters with %* or getting args one at a time with shift) and for each case, how to deal with irregular input in a way that is compatible with the other cases. If I don't find a solution, at least I'll post my findings. And if I don't have the energy to do that, I'll close the topic and assign points appropriately.
Thanks for your patience,
airvector
I'm working on the second part of the question on my end. I will post when I have sufficiently understood the way DOS deals with arguments in Call statements, For loop commands and regular batch calls, as well as the various contexts (calling from prompt or calling from within another script), and the various ways of getting argument values (getting all characters with %* or getting args one at a time with shift) and for each case, how to deal with irregular input in a way that is compatible with the other cases. If I don't find a solution, at least I'll post my findings. And if I don't have the energy to do that, I'll close the topic and assign points appropriately.
Thanks for your patience,
airvector
ASKER
Guys, I'm closing it here. Please look at my last comment and at the comment marked as best solution to further investigate this question.
Thanks to all who've helped!
airvector
Thanks to all who've helped!
airvector
However, in this case having tried it with this script I don't have any problems?!
trim " 12 "1" 23 "",
@echo off
set string=%~1
echo What it looks like before [%string%]
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
echo to trailing
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
:return
echo What it looks like afterwards [%string%]
echo "%string%"
The outer for loop will choke on the funny " combinations, could I suggest instead bringing it all into one batch and using something like this:
@echo off
call :trimspaces "%~1"
call :trimspaces "%~2"
call :trimspaces "%~3"
call :trimspaces "%~4"
pause
exit /b
:trimspaces
set string=%~1
echo What it looks like before [%string%]
:leading
if "%string:~0,1%"==" " (
set string=%string:~1%
goto leading
)
echo to trailing
:trailing
if "%string:~-1%"==" " (
set string=%string:~0,-1%
goto trailing
)
:return
echo What it looks like afterwards [%string%]
echo "%string%"
Output I get from that is:
Open in new window