Как вы удаляете кавычки из строки ECHO в командном файле Windows? - PullRequest
38 голосов
/ 30 апреля 2009

У меня есть пакетный файл Windows, который я создаю, но мне нужно ECHO большая сложная строка, поэтому мне приходится ставить двойные кавычки с обеих сторон. Проблема в том, что кавычки также выводятся в файл, в который я пишу. Как вы ECHO строку, как это и лишить кавычки?

UPDATE:

Я провел последние два дня, работая над этим, и, наконец, смог кое-что запутать. Ответ Ричарда сработал, чтобы отбросить кавычки, но даже когда я поместил ECHO в подпрограмму и непосредственно вывел строку, Windows все еще зависал на символах в строке. Я приму ответ Ричарда, так как он отвечает на заданный вопрос.

В итоге я использовал решение sed Грега, но мне пришлось изменить его из-за ошибок / функций sed / windows (не помогло, что оно пришло без документации). Есть несколько предостережений относительно использования sed в Windows: вы должны использовать двойные кавычки вместо одинарных кавычек, вы не можете экранировать двойные кавычки в строке напрямую, вы должны заключать в кавычки строку, экранировать с помощью ^ (так что ^ " ) затем передайте цитату для следующего раздела. Кроме того, кто-то указал, что, если вы передаете входную информацию в sed, есть ошибка, связанная с наличием канала в строке (я не смог проверить это, так как в моем окончательном решении я просто нашел способ не иметь все кавычки в середине строки, а просто удалить все кавычки, Я так и не смог удалить конечную кавычку самостоятельно. ) Спасибо за помощь.

Ответы [ 12 ]

54 голосов
/ 30 апреля 2009

Команда call имеет встроенную функциональность. Чтобы процитировать справку для вызова:

 Substitution of batch parameters (%n) has been enhanced.  You can
 now use the following optional syntax:

 %~1         - expands %1 removing any surrounding quotes (")

Вот примитивный пример:

@echo off
setlocal
set mystring="this is some quoted text"
echo mystring=%mystring%
call :dequote %mystring%
echo ret=%ret%
endlocal
goto :eof

:dequote
setlocal
rem The tilde in the next line is the really important bit.
set thestring=%~1
endlocal&set ret=%thestring%
goto :eof

Выход:

C:\>dequote
mystring="this is some quoted text"
ret=this is some quoted text

Я должен отдать должное технике «туннелирования переменных среды» (endlocal & set ret =% thestring%) Тиму Хиллу, «Сценарии оболочки Windows NT» . Это единственная книга, которую я когда-либо нашел, в которой рассматриваются командные файлы любой глубины.

10 голосов
/ 06 сентября 2012

Вы можете использовать конструкцию %var:x=y%, которая заменяет все x на y.

Посмотрите на этот пример, что он может сделать:

set I="Text in quotes"
rem next line replaces " with blanks
set J=%I:"=%
echo original %I%
rem next line replaces the string 'in' with the string 'without' 
echo stripped %J:in=without%
7 голосов
/ 22 декабря 2016

Для печати строки без кавычек можно использовать следующий подход:

echo|set /p="<h1>Hello</h1>"
3 голосов
/ 25 апреля 2017

Чтобы удалить все кавычки из заданной переменной, вам нужно Расширение отложенной переменной, чтобы безопасно развернуть переменную и обработать ее. Расширение с использованием знаков процента (т. Е. %VAR% и %1) по своей сути небезопасно (они уязвимы для введения команд; прочтите это для получения подробной информации ).

SETLOCAL EnableDelayedExpansion
SET VAR=A ^"quoted^" text.
REM This strips all quotes from VAR:
ECHO !VAR:^"=!
REM Really that's it.

Чтобы вырезать кавычки из текстового файла или вывода команды, все усложняется, потому что с отложенным расширением строка типа !VAR! в текстовом документе будет расширяться (в пределах расширения %%i в FOR /F), когда оно не должно. (Это еще одна уязвимость - раскрытие информации, которая не документирована в других местах.)

Для безопасного анализа документа требуется переключение между средой с отложенным расширением и -disabled.

REM Suppose we fetch the text from text.txt

SETLOCAL DisableDelayedExpansion
REM The FOR options here employs a trick to disable both "delims"
REM characters (i.e. field separators) and "eol" character (i.e. comment
REM character).
FOR /F delims^=^ eol^= %%L IN (text.txt) DO (

    REM This expansion is safe because cmd.exe expands %%L after quotes
    REM parsing as long as DelayedExpansion is Disabled. Even when %%L
    REM can contain quotes, carets and exclamation marks.
    SET "line=%%L"

    CALL :strip_quotes
    REM Print out the result. (We can't use !line! here without delayed
    REM expansion, so do so in a subroutine.)
    CALL :print_line
)
ENDLOCAL
GOTO :EOF

REM Reads !line! variable and strips quotes from it.
:strip_quotes
    SETLOCAL EnableDelayedExpansion
    SET line=!line:^"=!

    REM Make the variable out of SETLOCAL
    REM I'm expecting you know how this works:
    REM (You may use ampersand instead:
    REM `ENDLOCAL & SET "line=%line%"`
    REM I just present another way that works.)
    (
    ENDLOCAL
    SET "line=%line%"
    )
GOTO :EOF

:print_line
    SETLOCAL EnableDelayedExpansion
    ECHO !line!
    ENDLOCAL
GOTO :EOF

delims^=^ eol^= в приведенном выше коде, вероятно, нуждается в объяснении: Это эффективно отключает как символы «разделители» (то есть разделители полей), так и символ «eol» (то есть символ комментария). Без этого «delims» по умолчанию будет табуляцией и пробелом, а «eol» по умолчанию будет точкой с запятой.

  • Маркер eol= всегда читается в зависимости от того, какой следующий символ находится после знака равенства. Чтобы отключить его, этот токен должен находиться в конце строки параметров, чтобы никакие символы не могли использоваться для «eol», фактически отключая его. Если строка параметров заключена в кавычки, она может использовать кавычку (") в качестве" eol ", поэтому мы не должны заключать в кавычки строку параметров.
  • Параметр delims=, если он не является последним параметром в строке параметров, будет завершен пробелом. (Чтобы включить пробел в «разделители», это должен быть последний параметр из FOR /F параметров.) Поэтому delims=, за которым следует пробел, а затем другой параметр отключает «разделители».
2 голосов
/ 29 мая 2015

Я знаю, что это на самом деле не для автора, но если вам нужно отправить какой-то текст в файл без кавычек - решение ниже работает для меня. Вам не нужно использовать кавычки в команде echo, просто заключите всю команду в квадратные скобки.

(
    echo first very long line
    echo second very long line with %lots% %of% %values%
) >"%filename%"
2 голосов
/ 22 апреля 2012

Следующий пакетный файл запускает серию программ с задержкой после каждой.

Проблема состоит в том, чтобы передать командную строку с параметрами для каждой программы. Это требует кавычек вокруг аргумента программы, которые удаляются при выполнении вызова. Это иллюстрирует несколько методов обработки пакетных файлов.

Посмотрите в локальной подпрограмме: mystart, как передается аргумент в кавычках и как они удаляются.

@echo off

rem http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/if.mspx?mfr=true

rem Start programs with delay

rem  Wait n seconds
rem  n number retries to communicate with the IP address
rem  1000 milliseconds between the retries
rem  127.0.0.1 is the LocalHost
rem  start /b (silent)  /min (minimized) /belownormal (lower priority)
rem  /normal provides a no-op switch to hold the place of argument 1

rem  start  /normal "Opinions"  %SystemRoot%\explorer.exe /e,d:\agar\jobs\opinion
rem  ping 127.0.0.1 -n 8 -w 1000 > nul

rem   Remove quotes in Batch
rem     http://ss64.com/nt/syntax-dequote.html
rem   String manipulation in Batch
rem     http://www.dostips.com/DtTipsStringManipulation.php
rem   ^ line continuation
rem   
rem   set p="One Two"      p has the exact value  "One Two" including the quotes           
rem   set p=%p:~1,-1%      Removes the first and last characters
rem   set p=%p:"=%         Removes all double-quotes
rem   set p=%p:cat=mouse%  Replaces cat with mouse

rem  ping 127.0.0.1 -n 12 -w 1000 > nul
rem        1       2            3                                                         4

@echo on
call :mystart /b/min  "Opinions"   "%SystemRoot%\explorer.exe  /e,d:\agar\jobs\opinion"   8  
@echo on
call :mystart /b/min  "Notepad++"  D:\Prog_D\Notepad++\notepad++.exe  14
@echo on
call :mystart /normal "Firefox"    D:\Prog_D\Firefox\firefox.exe      20
@rem call :mystart /b/min "ProcessExplorer"  D:\Prog_D\AntiVirus\SysInternals\procexp.exe  8
@echo on
call :mystart /b/min/belownormal "Outlook" D:\Prog_D\MSOffice\OFFICE11\outlook.exe  2
@echo off
goto:eof

:mystart
@echo off
 rem  %3 is "program-path  arguments" with the quotes. We remove the quotes
 rem  %4 is seconds to wait after starting that program
 set p=%3
 set p=%p:"=%
 start  %1  %2  %p% 
 ping 127.0.0.1 -n %4 -w 1000 > nul
 goto:eof
2 голосов
/ 30 апреля 2009

Ответ выше (начиная с: DeQuote) предполагает, что отложенное расширение переменной среды включено. Из cmd /?:

Задержка расширения переменной среды по умолчанию НЕ включена. Вы может включить или отключить отложенное расширение переменной среды для конкретный вызов CMD.EXE с ключом / V: ON или / V: OFF. Вы может включить или отключить завершение для всех вызовов CMD.EXE на сеанс входа в систему компьютера и / или пользователя путем установки одного или обоих параметров следующие значения REG_DWORD в реестре с использованием REGEDT32.EXE:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion

    and/or

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\DelayedExpansion

до 0x1 или 0x0. Пользовательский параметр имеет приоритет над настройка машины. Ключи командной строки имеют приоритет над настройки реестра.

Если включено замедленное расширение переменной среды, то восклицательный знак символ может быть использован для замены значения переменной среды во время исполнения.

2 голосов
/ 30 апреля 2009

Это превратит "C:\Program Files\somefile.txt" в C:\Program Files\somefile.txt при сохранении таких дел, как Height=5'6" и Symbols="!@#

:DeQuote

SET _DeQuoteVar=%1
CALL SET _DeQuoteString=%%!_DeQuoteVar!%%
IF [!_DeQuoteString:~0^,1!]==[^"] (
IF [!_DeQuoteString:~-1!]==[^"] (
SET _DeQuoteString=!_DeQuoteString:~1,-1!
) ELSE (GOTO :EOF)
) ELSE (GOTO :EOF)
SET !_DeQuoteVar!=!_DeQuoteString!
SET _DeQuoteVar=
SET _DeQuoteString=
GOTO :EOF

Пример

SetLocal EnableDelayedExpansion
set _MyVariable = "C:\Program Files\ss64\"
CALL :dequote _MyVariable
echo %_MyVariable%
1 голос
/ 23 октября 2018

Ответ Даниэля Будзыньски блестящий. Это работает даже в ситуациях, когда в выводе есть специальные символы. Например:

C:\> for /f "usebackq tokens=2 delims=:" %i in (`%comspec%\..\ping -n 1 -w 200 10.200.1.1 ^| \
     findstr /c:"TTL="`) do echo|set /p="%i"

bytes=32 time<1ms TTL=255

Если вы попытаетесь попробовать простое эхо без кавычек, вы получите ошибку из-за «<» в переменной: </p>

C:\> set "output=bytes=32 time<1ms TTL=255"
C:\> echo %output%
The system cannot find the file specified.

C:\> echo|set /p="%output%"
bytes=32 time<1ms TTL=255
1 голос
/ 17 марта 2013

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

Пример 1: 5-строчное (с комментариями) решение.

REM Set your string
SET STR=" <output file>    (Optional) If specified this is the name of your edited file"

REM Echo your string into the FOR loop
FOR /F "usebackq tokens=*" %%A IN (`ECHO %STR%`) DO (
    REM Use the "~" syntax modifier to strip the surrounding quotation marks
    ECHO %%~A
)

Пример 2: Пример из 1 строки в реальном мире.

SET STR=" <output file>    (Optional) If specified this is the name of your edited file"

FOR /F "usebackq tokens=*" %%A IN (`ECHO %STR%`) DO @ECHO %%~A

Мне интересно, что внутреннее эхо игнорирует символы перенаправления '<' и '>'.
Если вы выполните ECHO asdfsd>asdfasd, вы запишите файл вместо std out.

Надеюсь, это поможет:)

Edit:

Я подумал об этом и понял, что есть еще более легкий (и менее хакерский) способ сделать то же самое. Используйте расширенную замену / расширение переменной (см. HELP SET) следующим образом:

SET STR=" <output file>    (Optional) If specified this is the name of your edited file"

ECHO %STR:~1,-1%

Это напечатает все, кроме первого и последнего символов (ваши кавычки). Я бы рекомендовал использовать SETLOCAL ENABLEDELAYEDEXPANSION тоже. Если вам нужно выяснить, где в строке находятся кавычки, вы можете использовать FINDSTR для получения символов #.

...