2015-12-27 3 views
2

Мне нужно перенаправить файл vbs через пакетный файл.Как избежать «&» при создании файла через командный файл

Мой код, как:

@echo off 
echo Option Explicit>> weather.vbs 
echo Dim LogFile,Ws,Tag,Content>> weather.vbs 
echo LogFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName, .)) & txt >> weather.vbs 
echo Set Ws = CreateObject(wscript.Shell) >> weather.vbs 
echo With CreateObject(InternetExplorer.Application) >> weather.vbs 
echo  .Visible = False>> weather.vbs 
echo .Navigate http://aldweathersh2.blogspot.in/ >> weather.vbs 
echo Do Until .ReadyState = 4 >> weather.vbs 
echo   Wscript.Sleep 6000>> weather.vbs 
echo  Loop>> weather.vbs 
echo  For Each Tag In .Document.GetElementsByTagName(script) >> weather.vbs 
echo   Tag.OuterHtml = >> weather.vbs 
echo  Next>> weather.vbs 
echo  For Each Tag In .Document.GetElementsByTagName(noscript) >> weather.vbs 
echo   Tag.OuterHtml = >> weather.vbs 
echo  Next>> weather.vbs 
echo  Content = .Document.GetElementsByTagName(body)(0).InnerText >> weather.vbs 
echo  Do While InStr(Content, vbCrLf & vbCrLf)>>weather.vbs 
echo   Content = Replace(Content, vbCrLf & vbCrLf, vbCrLf) >> weather.vbs 
echo  Loop >> weather.vbs 
echo  WriteLog Content,LogFile >> weather.vbs 
echo .Quit>> weather.vbs 
echo End With>> weather.vbs 
echo '******************************************************************* >> weather.vbs 
echo Sub WriteLog(strText,LogFile) >> weather.vbs 
echo Dim fso,ts>> weather.vbs 
echo  Const ForWriting = 2 >> weather.vbs 
echo Set fso = CreateObject(Scripting.FileSystemObject) >> weather.vbs 
echo  Set ts = fso.OpenTextFile (LogFile,ForWriting,True,-1) >> weather.vbs 
echo  ts.WriteLine strText>> weather.vbs 
echo  ts.Close>> weather.vbs 
echo End Sub>> weather.vbs 
echo '******************************************************************>> weather.vbs 
pause 

Проблема возникает с пакетным файлом при выполнении строки, содержащую «&» в нем. Каждый раз, когда он перерывает перенаправление с помощью «&».

Ошибка:

LogFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName, .)) 
'txt' is not recognized as an internal or external command, 
operable program or batch file. 
    Do While InStr(Content, vbCrLf 
'vbCrLf)' is not recognized as an internal or external command, 
operable program or batch file. 
     Content = Replace(Content, vbCrLf 
'vbCrLf' is not recognized as an internal or external command, 
operable program or batch file. 

Есть ли способ, чтобы перенаправить строки с «&» в пакетном файле?

+2

Можете ли вы избежать амперсанд (&), предварив его с кареткой (^)? – Norman

ответ

2

Побег & (и других проблемных символов) с ^, так что

echo  Do While InStr(Content, vbCrLf ^& vbCrLf)>>weather.vbs 
+0

Вы также должны избегать ')' и, возможно, '(' потому что круглые скобки открывают/закрывают блоки кода ... – aschipfl

+0

Пока нет в инструкции 'echo'. – GolezTrol

+0

Пока' echo' не находится внутри блока, escaping необязательно, как только у вас есть, например, '(echo a (b) c)', как должен парсер знать, который ')' является закрывающим? поэтому вам обязательно понадобится '(echo a (b ^) c)'; Я предпочитаю избегать и открытия (хотя и не обязательно) ради удобочитаемости, поэтому я бы использовал '(echo a^(b ^) c)' ... – aschipfl

3

Ой.

GolezTrol предоставил прямой ответ на ваш вопрос - избегайте & как ^&.

Но вот полезный совет, хотя на самом деле он не отвечает на ваш вопрос. При перенаправлении группы команд в один и тот же файл гораздо эффективнее (и проще читать) перенаправлять один раз.

(
    echo line 1 
    echo line 2 
    echo line 3 
)>output.txt 

Однако выше заставит вас, чтобы избежать какой-либо ), как ^) в тексте.

В качестве альтернативы вы можете перенаправить CALL и не беспокоиться о побеге ).

call :write >output.txt 
exit /b 
:write 
echo line 1 
echo line 2 
echo line 3 
exit /b 

Но на самом деле существует намного лучший способ, который устраняет необходимость беспокоиться о побеге. Префикс каждой строки ::: и используйте FINDSTR для поиска строк, а FOR/F - для удаления префикса. Важно, чтобы ни одна из ваших нужных текстовых строк не начиналась с :.

@echo off 
:::Option Explicit 
:::Dim LogFile,Ws,Tag,Content 
:::LogFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName, .)) & txt 
:::Set Ws = CreateObject(wscript.Shell) 
:::With CreateObject(InternetExplorer.Application) 
::: .Visible = False 
::: .Navigate http://aldweathersh2.blogspot.in/ 
::: Do Until .ReadyState = 4 
:::  Wscript.Sleep 6000 
::: Loop 
::: For Each Tag In .Document.GetElementsByTagName(script) 
:::  Tag.OuterHtml = 
::: Next 
::: For Each Tag In .Document.GetElementsByTagName(noscript) 
:::  Tag.OuterHtml = 
::: Next 
::: Content = .Document.GetElementsByTagName(body)(0).InnerText 
::: Do While InStr(Content, vbCrLf & vbCrLf) 
:::  Content = Replace(Content, vbCrLf & vbCrLf, vbCrLf) 
::: Loop 
::: WriteLog Content,LogFile 
::: .Quit 
:::End With 
:::'******************************************************************* 
:::Sub WriteLog(strText,LogFile) 
::: Dim fso,ts 
::: Const ForWriting = 2 
::: Set fso = CreateObject(Scripting.FileSystemObject) 
::: Set ts = fso.OpenTextFile (LogFile,ForWriting,True,-1) 
::: ts.WriteLine strText 
::: ts.Close 
:::End Sub 
:::'****************************************************************** 
>weather.vbs (for /f "delims=: tokens=*" %%A in ('findstr "^:::" "%~f0"') do echo(%%A) 

echo( является неясным синтаксис, который способен печатать строки, которые являются пустыми или состоять из ничего, кроме пространства. Он более надежен, чем echo. Похоже, что это испортило бы круглые скобки, но это не так. У вас нет пустых строк в тексте, так что это не проблема, но это хороший трюк.

:: действует как комментарий, поэтому эти строки не будут выполнены.

Есть два случая, когда выше метод может потерпеть неудачу с фатальной ошибкой синтаксиса:

  • Ваш текст содержит %~, который получает разобранную как недействительное расширение аргумента.
  • Ваш текст содержит %var:= где var - это имя переменной окружения. Выражение анализируется как операция поиска/замены недействительной переменной.

Если вы столкнулись с одной из вышеуказанных проблем, вы можете просто поместить свой текст в нижней части скрипта с помощью EXIT/B перед ним.

Если некоторые из ваших строк начинаются с :, то вы просто модифицируете префикс, чтобы закончить символом, который никогда не начинается с строки, и немного измените FOR/F. Например, предположим, что ни одна строка никогда не начинается с }

::}Line 1 
::}Line 2 
::}Line 3 
>output.txt (for /f "delims=} tokens=1*" %%A in ('findstr "^::}" "%~f0"') do echo(%%B) 

Другая небольшая модификация позволяет внедрять несколько независимых блоков текста

::A}Line 1 
::A}Line 2 
::A}Line 3 

::B}Line A 
::B}Line B 
::B}Line C 

>a.txt (for /f "delims=} tokens=1*" %%A in ('findstr "^::A}" "%~f0"') do echo(%%B) 
>b.txt (for /f "delims=} tokens=1*" %%A in ('findstr "^::B}" "%~f0"') do echo(%%B) 
+0

Человек, ваш ответ заставляет меня стыдиться. : /: D – GolezTrol