Втеча з подвійних лапок у пакетному сценарії


91

Як я міг би замінити всі подвійні лапки в параметрах мого командного файлу на подвійні лапки, що втекли? Це мій поточний пакетний файл, який розширює всі параметри командного рядка всередині рядка:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

Потім він використовує цей рядок для виклику bash Cygwin, виконуючи крос-компілятор Linux. На жаль, я отримую такі параметри, як передані в мій командний файл:

"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions 
-Wno-inline -Wall  -DNDEBUG   -c 
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o" 
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"

Де перша лапка навколо першого переданого шляху передчасно закінчує рядок, що передається GCC, а решту параметрів передає безпосередньо в bash (що не вдається вражаюче).

Я думаю, якщо я зможу об'єднати параметри в єдиний рядок, то уникну лапок, це повинно працювати нормально, але мені важко визначити, як це зробити. Хтось знає?

Відповіді:


103

Символ екранування в пакетних сценаріях є ^. Але для рядків із подвійними лапками подвойте лапки:

"string with an embedded "" character"

5
подвоєння цитат у мене не працювало, але ^ працювало як чемпіон.
davenpcj

25
^є символом втечі лише в рядках без лапок ; у рядках із подвійними лапками це трактується як літерал. На відміну від Unix (POSIX-подібних) оболонок, cmd.exeНЕ пропонує стандартизованої обробки оболонок подвійних лапок всередині рядка з подвійними лапками, а інтерпретація залишається для програми, що викликається (продовження в наступному коментарі).
mklement0

9
(продовження з попереднього коментаря) На практиці більшість виконуваних файлів / інтерпретаторів сценаріїв застосовують конвенцію C про очікувані "символи. для екранування як \"всередині рядка з подвійними лапками (застосовується принаймні до: C / C ++, Python, Perl, Ruby). З іншого боку, ""визнаються тільки в меншості випадків: У параметрах , переданих в пакетні файли, "" буде визнана в якості вбудованої подвійної лапки, але зберігаються як у відповідному %<n>параметрі, навіть після видалення огороджувальних подвійних лапок з %~<n>. Python також люб’язно визнає ""альтернативу\" .
mklement0

89

Власна відповідь eplawless просто та ефективно вирішує його конкретну проблему: вона замінює всі "екземпляри у всьому списку аргументів на \", саме таким чином Bash вимагає представлення подвійних лапок всередині рядка з подвійними лапками.

Щоб загалом відповісти на питання про те, як уникнути подвійних лапок всередині рядка з подвійними лапками, використовуючиcmd.exe інтерпретатор командного рядка Windows (будь то в командному рядку - часто все ще помилково називається "підказкою DOS" - або в командному файлі): Дивіться знизу, щоб подивитися PowerShell .

tl; dr :

  • Ви повинні використовувати"" при передачі рядка ((нічого) пакетного файлу, і ви можете використовувати ""з програмами, створеними за допомогою компіляторів C / C ++ /. NET від Microsoft (які також приймають \"), які в Windows включають Python та Node.js :

    • Приклад: foo.bat "We had 3"" of rain."

    • Наступне стосується лише пакетних файлів:

      • ""це єдиний спосіб отримати інтерпретатор команд ( cmd.exe) для обробки цілого рядка з подвійними лапками як одного аргументу.

      • На жаль, однак, не лише збережені вкладені подвійні лапки (як зазвичай), але і подвоєні екрановані, тому отримання задуманого рядка є двоступеневим процесом; наприклад, припускаючи, що рядок із подвійними лапками передається як 1-й аргумент %1:

      • set "str=%~1"прибирає укладені подвійні лапки; set "str=%str:""="%"потім перетворює подвоєні подвійні лапки в одинарні.
        Обов’язково використовуйте вкладені подвійні лапки навколо частин присвоєння, щоб запобігти небажаному тлумаченню значень.

  • \"це потрібно - як єдиний варіант - багатьма іншими програмами , (! наприклад, Ruby, Perl, і навіть Microsoft власний Windows PowerShell ()), але ЙОГО ВИКОРИСТАННЯ НЕ SAFE :

    • \"це те, що вимагається багатьом виконуваним файлам і інтерпретаторам - включаючи Windows PowerShell - при передачі рядків ззовні - або, у випадку компіляторів Microsoft, підтримка як альтернатива "" - в кінцевому рахунку, цільова програма повинна проаналізувати список аргументів .
      • Приклад: foo.exe "We had 3\" of rain."
    • ОДНО, ВИКОРИСТАННЯ \"МОЖЕ РЕЗУЛЬТАТУВАТИ НЕБАЖЛИВЕ, АРТІЦІЙНЕ ВИКОНАННЯ КОМАНД і / або ВХОДИ / ВИХОДНІ НАПРЯМКИ :
      • Наступні символи представляють цей ризик: & | < >
      • Наприклад, наступне призводить до ненавмисного виконання verкоманди; див. далі пояснення та наступний пункт для обхідного шляху:
        • foo.exe "3\" of snow" "& ver."
    • Для Windows PowerShell , \""і "^""надійні, але обмежені варіанти (дивись розділ «Виклик CLI PowerShell в ...» нижче).
  • Якщо вам потрібно скористатися \", існує лише 3 безпечні підходи , які, проте, досить громіздкі : Підказка капелюха ТС за його допомогою.

    • Використовуючи (можливо, вибіркове ) затримку розширення змінної у вашому пакетному файлі, ви можете зберігати літерал \"у змінній та посилатися на цю змінну всередині "..."рядка, використовуючи !var!синтаксис - див . Корисну відповідь TS .

      • Вищезазначений підхід, незважаючи на громіздкість, має ту перевагу, що ви можете застосовувати його методично і що він працює надійно , з будь-яким входом.
    • Лише з ЛІТЕРАЛЬНИМИ рядками - такими, що НЕ включають ЗМІННИХ - ви отримуєте аналогічний методичний підхід: категорично ^-бежать всі cmd.exe метасимволи: " & | < > і - якщо ви також хочете придушити змінне розширення - %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

    • В іншому випадку, ви повинні сформулювати свій рядок на основі розпізнавання, які частини рядка cmd.exeвважають котируваннями через неправильне тлумачення\" як закриваючі роздільники:

      • в буквальних частинах , що містять метасимволи: ^екранують їх; використовуючи приклад, наведений вище, це &те, що має бути ^-escaped:
        foo.exe "3\" of snow" "^& ver."

      • частинами з %...%посиланнями на змінні -style : переконайтеся, що вони cmd.exeвважають їх частиною "..."рядка і що значення змінних самі не мають вбудованих незбалансованих лапок - що навіть не завжди можливо .

Для довідкової інформації читайте далі.


Передумови

Примітка: Це базується на моїх власних експериментах. Повідомте мене, якщо я помиляюся.

POSIX-подібні оболонки, такі як Bash на Unix-подібних системах, токенізують список аргументів (рядок) перед передачею аргументів окремо цільовій програмі: серед інших розширень вони розділяють список аргументів на окремі слова (розбиття слів) і видаляють символи цитування з отримані слова (вилучення цитати). Цільовій програмі вручається масив з окремих аргументів , з синтаксичними цитати видалені .

На відміну від цього, інтерпретатор команд Windows, очевидно, не маркує список аргументів, а просто передає єдиний рядок, що включає всі аргументи, включаючи символи цитування. - до цільової програми.
Однак відбувається певна попередня обробка перед передачею одного рядка цільовій програмі: ^escape символи. поза рядків із подвійними лапками видаляються (вони уникають наступного символу), а посилання на змінні (наприклад, %USERNAME%) спочатку інтерполюються .

Таким чином, на відміну від Unix, цільова програма несе відповідальність за синтаксичний аналіз, щоб проаналізувати рядок аргументів і розбити його на окремі аргументи із видаленими лапками. Таким чином, різні програми можуть гіпотетично вимагати різних методів екранування, і немає єдиного механізму екранування, який гарантовано буде працювати з усіма програмами - https://stackoverflow.com/a/4094897/45375 містить чудові передумови про анархію, тобто командний рядок Windows синтаксичний розбір.

На практиці \"це дуже поширене, але НЕ БЕЗПЕЧНО , як уже згадувалося вище:

Так як cmd.exeсам по собі не визнає \"як бігла прямі подвійні лапки, він може неправильно витлумачити пізніше лексеми в командному рядку, без лапок і потенційно інтерпретувати їх як команду і / або введення / виведення перенаправлення .
У двох словах: проблемна поверхня, якщо будь-який із наведених нижче символів слідує за відкриттям або незбалансованим \" :& | < > ; наприклад:

foo.exe "3\" of snow" "& ver."

cmd.exeбачить наступні лексеми, отримані в результаті неправильного тлумачення \"як звичайні подвійні лапки:

  • "3\"
  • of
  • snow" "
  • відпочинок: & ver.

Оскільки cmd.exeвважає, що & ver.це не котирування , воно інтерпретує це як &(оператор послідовності команд), а потім ім'я команди для виконання ( ver.- .ігнорується;ver про cmd.exeверсію звітів ).
Загальний ефект:

  • Перший, foo.exe викликається лише першими 3 маркерами.
  • Потім, команда ver виконується.

Навіть у тих випадках, коли випадкова команда не завдає шкоди, ваша загальна команда не працюватиме так, як було розроблено, враховуючи те, що не всі аргументи передаються їй.

Багато компілятори / інтерпретатори розпізнають ТІЛЬКИ\" - наприклад, компілятор GNU C / C ++, Python, Perl, Ruby, навіть власна оболонка Windows PowerShell від Microsoft при виклику cmd.exe- і, за винятком (з обмеженнями) для Windows PowerShell with \"", для них немає простого рішення до цієї проблеми.
По суті, вам слід було б заздалегідь знати, які частини вашого командного рядка неправильно трактуються як нецитовані та вибірково^ нецитовані уникати всіх екземплярів & | < >цих частин.

Навпаки, використання ""є БЕЗПЕЧНО , але, на жаль, воно підтримується лише виконуваними файлами та пакетними файлами на базі компілятора Microsoft (у випадку з пакетними файлами, з примхами, про які йшлося вище), що особливо виключає PowerShell - див. Наступний розділ.


Виклик CLI PowerShell з cmd.exeоболонок, схожих на POSIX:

Примітка: Дивіться нижній розділ, щоб дізнатись, як обробляється цитування в PowerShell.

При виклику ззовні - наприклад, з cmd.exeкомандного рядка чи командного файлу:

  • PowerShell [Core] v6 + тепер правильно розпізнає"" (крім\"), що є безпечним у використанні та зберігає пробіли .

    • pwsh -c " ""a & c"".length " не ламається і правильно дає 6
  • Windows PowerShell (застаріле видання, остання версія якого 5.1) розпізнає лише, \" а в Windows також """і більш надійний \""/"^"" (навіть якщо внутрішньо PowerShell використовує`як вхідний символ у рядках із подвійними лапками, а також приймає""- див. Нижній розділ):

Виклик Windows PowerShell зcmd.exe / командного файлу:

  • "" перерви , оскільки це принципово не підтримується:

    • powershell -c " ""ab c"".length " -> помилка "У рядку відсутній термінатор"
  • \"і """ працюють в принципі , але не в безпеці :

    • powershell -c " \"ab c\".length "працює за призначенням: видає 5(зверніть увагу на 2 пробіли)
    • Але це не безпечно, тому що cmd.exeметасимволи порушують команду, якщо не захищено :
      powershell -c " \"a& c\".length " перерви , через те &, що потрібно було б уникнути як^&
  • \""є безпечним , але нормалізують інтер'єр прогалини , які можуть бути небажаними:

    • powershell -c " \""a& c\"".length "виводить 4(!), оскільки 2 пробіли нормуються до 1.
  • "^""це кращий вибір для Windows PowerShell конкретно , де вона є безпечною і пробільним зберігає, але з PowerShell Ядром (на Windows) , це те ж саме , як\"" , наприклад, whitespace- нормалізації . За відкриття цього підходу Venryx заслуговує на честь .

    • powershell -c " "^""a& c"^"".length " працює : не ламається - попри &- і виводить 5, тобто правильно збережений пробіл.

    • Ядро PowerShell : pwsh -c " "^""a& c"^"".length " працює , але видає 4, тобто нормалізує пробіли , як \""це робить.

На Unix-подібних платформах (Linux, macOS) під час виклику CLI PowerShell [Core]pwsh з POSIX-подібної оболонки, наприкладbash :

Ви повинні використовувати\" , що, однак, є і безпечним, і зберігаючи пробіли :

$ pwsh -c " \"a&  c|\".length" # OK: 5

Пов’язана інформація

  • ^може використовуватися лише як символ втечі в рядках без лапок - всередині рядків із подвійними лапками, ^не є особливим і трактується як літерал.

    • CAVEAT : Використання ^параметрів, переданих callоператору, порушено (це стосується як використання call: виклику іншого пакетного файлу або двійкового файлу, так і виклику підпрограми в тому ж пакетному файлі):
      • ^екземпляри в подвійних лапках значень незрозуміло подвоюються , змінюючи передане значення: наприклад, якщо змінна %v%містить літеральне значення a^b, call :foo "%v%"присвоює "a^^b"(!) %1першому параметру в підпрограмі :foo.
      • Некотируваних використання ^з callбуде повністю непрацездатним в тому , що ^не може більше використовуватися , щоб екранувати спеціальні символи : наприклад,call foo.cmd a^&bспокійно перерви (замість проходження буквальнимa&bтежfoo.cmd, як було б у випадку безcall) -foo.cmdніколи навітьвикликається, по крайней мерена ОС Windows (!) 7.
  • На% жаль, уникнення літералу - це особливий випадок , який вимагає чіткого синтаксису, залежно від того, вказаний рядок у командному рядку проти всередині командного файлу ; див. https://stackoverflow.com/a/31420292/45375

    • Короткий зміст: використовуйте всередині командного файлу %%. У командному рядку %неможливо уникнути екранування, але якщо розмістити a ^на початку, в кінці або всередині імені змінної у рядку без котирувань (наприклад, echo %^foo%), ви можете запобігти розширенню змінної (інтерполяція); %екземпляри в командному рядку, які не є частиною посилання на змінну, розглядаються як літерали (наприклад, 100%).
  • Як правило, для безпечної роботи зі значеннями змінних, які можуть містити пробіли та спеціальні символи :

    • Призначення : включіть і ім’я змінної, і значення в одну пару подвійних лапок ; наприклад, set "v=a & b"присвоює значення a & bзмінної буквальному значенню %v%(навпаки, set v="a & b"це зробить подвійні лапки частиною значення). Уникайте буквальних %примірників як %%(працює лише в пакетних файлах - див. Вище).
    • Посилання : Посилання на змінні з подвійними лапками, щоб переконатися, що їх значення не інтерпольоване; наприклад, echo "%v%"не підпорядковує значення %v%інтерполяції та друку "a & b"(але зауважте, що подвійні лапки також завжди друкуються). Навпаки, echo %v%передає літерал aдо echo, інтерпретує &як оператор послідовності команд, і тому намагається виконати команду з іменем b.
      Також зверніть увагу на наведене вище застереження щодо повторного використання ^із callзаявою.
    • Зовнішні програми, як правило, піклуються про те, щоб усунути подвійні лапки навколо параметрів, але, як зазначалося, у пакетних файлах ви повинні це зробити самостійно (наприклад, %~1щоб видалити вкладені подвійні лапки з 1-го параметра), і, на жаль, прямого спосіб, про який я знаю, щоб echoдостовірно надрукувати значення змінної без додавання подвійних лапок .
      • Ніл пропонує обхідне рішення на forоснові, яке працює до тих пір, поки значення не має вбудованих подвійних лапок ; наприклад:
        set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exeзовсім НЕ визнають поодинокі -quotes , як роздільники рядків - вони розглядаються як літерали і зазвичай не можуть бути використані для визначення рядків з вкладеними пробілами; також випливає, що лексеми, що примикають до одинарних лапок, та будь-які лексеми між ними розглядаються як нецівовані cmd.exeта інтерпретуються відповідно.

    • Однак, враховуючи, що цільові програми в кінцевому підсумку виконують власний аналіз аргументів, деякі програми, такі як Ruby, розпізнають рядки з одинарними лапками навіть у Windows; навпаки, виконувані файли C / C ++, Perl та Python їх не розпізнають.
      Однак навіть якщо це підтримується цільовою програмою, не доцільно використовувати рядки з одинарними лапками, оскільки їх вміст не захищений від потенційно небажаної інтерпретації cmd.exe.

Цитуючи в PowerShell:

Windows PowerShell - набагато вдосконаленіша оболонка cmd.exe, і вона є частиною Windows вже багато років (а PowerShell Core також привнесла досвід PowerShell у macOS та Linux).

PowerShell працює послідовно внутрішньо щодо цитування:

  • всередині рядків із подвійними лапками , використовуйте `"або, ""щоб уникнути подвійних лапок
  • всередині рядків ''з одинарними лапками , використовуйте для уникнення одинарних лапок

Це працює в командному рядку PowerShell і при передачі параметрів в сценарії або функції PowerShell з в PowerShell.

(Як обговорювалося вище, передача захищеної подвійної лапки до PowerShell ззовні вимагає \"або, більш надійно,\"" - нічого іншого не працює).

На жаль, під час виклику зовнішніх програм із PowerShell ви стикаєтесь із необхідністю дотримуватись власних правил цитування PowerShell та уникати цільової програми:

Ця проблемна поведінка також обговорюється та узагальнюється у цій відповіді

Подвійні лапки всередині рядків з подвійними лапками :

Розглянемо рядок "3`" of rain", який PowerShell внутрішньо перекладає буквально 3" of rain.

Якщо ви хочете передати цей рядок зовнішній програмі, вам доведеться застосувати цільову програму, що виділяється, крім PowerShell ; скажімо, що ви хочете передати рядок програмі C, яка очікує, що вбудовані подвійні лапки будуть екрановані як \":

foo.exe "3\`" of rain"

Зверніть увагу , як і `" - зробити PowerShell щасливим - і\ - зробити цільову програму щасливим - повинен бути присутнім.

Та сама логіка застосовується до виклику командного файлу, де ""повинен бути використаний:

foo.bat "3`"`" of rain"

Навпаки, вбудовування одинарних лапок у рядок із подвійними лапками взагалі не вимагає екранування .

Одиночне -quotes всередині окремих -quoted рядків нічого НЕ вимагає додаткового втечі; розглянемо'2'' of snow', що таке PowerShell 'представлення2' of snow.

foo.exe '2'' of snow'
foo.bat '2'' of snow'

PowerShell переводить рядки з одним лапками у подвійні лапки, перш ніж передавати їх цільовій програмі.

Однак подвійні лапки всередині рядків з одинарними лапками , які не потребують екранування для PowerShell , все одно повинні бути екрановані для цільової програми :

foo.exe '3\" of rain'
foo.bat '3"" of rain'

PowerShell v3 представив магічний --%варіант , званий стоп-розбір символом , який полегшує деякі болю, пропускання нічого після того, як він необроблений до цільової програми, за винятком cmd.exe-Style середовища змінної посилання (наприклад, %USERNAME%), які будуть розширені; наприклад:

foo.exe --% "3\" of rain" -u %USERNAME%

Зверніть увагу, як достатньо виходу із вбудованого типу "як \"для цільової програми (а також не для PowerShell as \`").

Однак такий підхід:

  • не допускає екранування % символів, щоб уникнути розширення змінної середовища.
  • виключає безпосереднє використання змінних та виразів PowerShell; натомість командний рядок повинен бути вбудований у змінну рядка на першому кроці, а потім викликаний за Invoke-Expressionдопомогою другого.

Таким чином, незважаючи на численні досягнення, PowerShell не значно полегшив втечу під час виклику зовнішніх програм. Однак він ввів підтримку рядків з одинарними лапками.

Цікаво , якщо це принципово можливо в світі Windows , щоб коли - або переключитися на модель Unix від дозволяючи оболонки зробити все лексичне і котирування видалення передбачувана , вперед , незалежно від цільової програми , а потім викликати цільову програму, передаючи отримані жетони .


Гарний опис! Але ... Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...не дуже. Тильда видаляє лише зовнішні лапки, якщо вони присутні. Втрата карет є проблемою самого поводження. Зазвичай це set "param=%~1"вирішує.
jeb

Дякую, @jeb, проблема насправді не є специфічною для використання ~- я оновив свою відповідь, щоб відобразити моє нове розуміння - будь ласка, коментуйте, якщо ви помітили проблему. Чи є у вас пояснення подвоєння того, ^що відбувається автоматично, коли ви передаєте параметри в callоператор?
mklement0

3
Я можу лише здогадуватися, що хтось із MS вважав це блискучим. Що подвоєні каретки будуть автоматично видалені на другому етапі синтаксичного аналізу. Але це було великою невдачею, оскільки це не працює в лапках і ефективно запобігає виходу будь-яких спеціальних символів. Начебто call echo cat^^&dogце неможливо вирішити лише за допомогою будь-якої кількості
карет

Дякую, @jeb, я навіть не замислювався про використання котирувань^ with call, яке, як ви зазначаєте, погано порушено. Здається, що в call echo cat^&dog(сингл, ^який належним чином виходить з &) цільової команди ( echo) ніколи навіть не викликається (!) - вся команда тихо виходить з ладу. Відповідь я оновив відповідно.
mklement0

Приємна відповідь. Однак я б не рекомендував використовувати ""як екран, "але завжди \"(Див. Мою відповідь щодо менш небезпечного способу його використання з cmd). Я не знаю жодної офіційної документації, яка визначається ""як процитована цитата, але принаймні 2, що згадують\" : .NET і VS . Хоча Win32 api неправильно задокументовано, також дотримується цих правил.
TS

23

Зрештою Google придумав відповідь. Синтаксис для заміни рядків у пакетній програмі такий:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

Яка видає "тиражуй мене". Мій сценарій тепер виглядає так:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

Який замінює всі екземпляри "з \", правильно втекли для Баша.


9

Як доповнення до чудової відповіді mklement0 :

Майже всі виконувані файли приймаються \"як екрановані ". Безпечне використання в cmd, однак, майже можливе лише за допомогою DELAYEDEXPANSION.
Щоб явно надіслати літерал "якомусь процесу, призначте \"змінну середовища, а потім використовуйте цю змінну, щоразу, коли вам потрібно передати цитату. Приклад:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

Примітка SETLOCAL ENABLEDELAYEDEXPANSIONЗдається, працює лише в пакетних файлах. Щоб отримати DELAYEDEXPANSION в інтерактивному сеансі, почніть cmd /V:ON.

Якщо ваш пакетний файл не працює з DELAYEDEXPANSION, ви можете тимчасово його ввімкнути:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

Якщо ви хочете передати динамічний вміст із змінної, яка містить лапки, які є екранованими як "" ви можете замінити ""з \"на розширення:

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

Ця заміна небезпечна %...% розширенні стилю!

У разі ОП bash -c "g++-linux-4.1 !v_params:"=\"!" є безпечною версією.


Якщо з якихось причин навіть тимчасово ввімкнення DELAYEDEXPANSION не є можливим, читайте далі:

Використовуючи \" cmd трохи безпечніше, якщо завжди потрібно уникати спеціальних символів, а не просто іноді. (Рідше забути каретку, якщо вона послідовна ...)

Щоб досягти цього, перед будь-якою цитатою ^"слід поставити символи введення ( ), лапки, які повинні потрапити в дочірній процес, оскільки літерали повинні додатково уникати зворотного ходу ( \^"). ВСІ метасимволи оболонки також повинні бути захищені ^, наприклад &=> ^&; |=> ^|;>=>^> ; тощо

Приклад:

child ^"malicious argument\^"^&whoami^"

Джерело: Усі неправильно цитують аргументи командного рядка , див. "Кращий метод цитування"


Щоб передати динамічний вміст, потрібно забезпечити наступне:
Частина команди, яка містить змінну, повинна вважатися "у cmd.exeцитатах " (Це неможливо, якщо змінна може містити лапки - не пишіть%var:""=\"% ). Для цього останнє "перед змінною та перше "після змінної не ^-бежать. cmd-метасимволів між цими двома "не можна уникати. Приклад:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

Це небезпечно, якщо %dynamic_content%може містити неперевершені лапки.


Зрозуміло, спасибі. Так, категорично - ^уникнення всіх метасимволів працює надійно і може застосовуватися більш методично (проте це, очевидно, царський біль у тілі, яку ви вибрали). Я оновив свою відповідь відповідно (і надав вам кредит).
mklement0

@ mklement0 Дякую! Так, це справді біль. Це дратує, і все одно занадто легко забути метасимвол (тому я переважно використовую !q!спосіб). Примітка: Ваш відповідь трохи непослідовний після останнього редагування: Поруч з верхніми ви говорите: «Не НЕ використовувати ^"». Пізніше ви використовуєте ^"як частину обхідного шляху. Може ви могли б пояснити обидва шляхи? (1) Втеча з усіх метасимволів (більш методично) / (2) Вибіркове уникнення метасимволів у "не котируваних" регіонах (іноді це потрібно для передачі динамічного вмісту, наприклад foo.exe ^"danger ^& bar=\"%dynamic_content%\"^"- таким чином, змінна вказується для cmd)
TS

Гарна думка, дякую - відповідь оновлена. Я також зрозумів, що компілятор MS приймає \"і "". Я посилався на вашу відповідь щодо більш залученого підходу на основі змінних. Повідомте мене, чи це має сенс зараз.
mklement0

1
@ mklement0 Ваша відповідь завжди мала сенс :-) Я просто хотів дати кілька ідей щодо можливих покращень. Я також додав приклад про %dynamic_content%у свою відповідь. Ви вважаєте, що він досить детальний, чи мені потрібно пояснити більше?
TS

3
Класно, дякую, що повідомили. Хороша ідея локалізувати файл setlocal delayedexpansion, але закінчувати блок слід endlocalбез аргументу. Чесно кажучи, моя голова почала крутитися, подивилася на ваш Суть. Тут ми справді маємо справу з надзвичайними випадками, і я думаю, що майбутні читачі знайдуть усе необхідне між нашими двома відповідями.
mklement0

0

Якщо рядок уже в лапках, використовуйте іншу лапку, щоб звести нанівець її дію.

echo "Insert tablename(col1) Values('""val1""')" 

-3

Наприклад, для інструменту автоматизації Unreal Engine Automation, запущеного з командного файлу - це спрацювало для мене

наприклад: -cmdline = "-Messaging" -device = device -addcmdline = "- SessionId = session -SessionOwner = 'owner' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'список автоматизації ; тести тестів +, розділені + T1 + T2; закрити '"-запуск

Сподіваюся, це комусь допомагає, працювало на мене.


Спробуйте перегнати концепцію, яку ви дізналися, яку намагаєтесь поділити наочним прикладом, а не довгою, переважно жодною відповідною копією для вставки з вашої роботи.
run_the_race
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.