tl; dr
Использование встроенного "
в общей строке "..."
сопряжено с необходимостью избежать проблем.Если это возможно, проще всего создать команду PowerShell без встроенного "
:
powershell -Command "Compare-Object (Get-Content tex1.txt) (Get-Content tex2.txt) | Where-Object {$_.SideIndicator -eq '<='} | select inputobject | ft -hidetableheaders"
Продолжайте читать, если вам нужно использовать встроенный "
.
eryksun указывает, что ваша проблема в отсутствии экранирования встроенных "
символов. внутри общей строки "..."
, из-за чего cmd.exe
видит кратное строки, включая части, которые он считает без кавычек , что вызывает проблемы со специальными символами, такими как |
и <
- они никогда не достигают PowerShell .
Вложение двойные кавычки из cmd.exe
- сложное дело:
- Чтобы сделать
cmd.exe
счастливым, вам нужно удвоить встроенных "
символов.(""
) - Отдельно, чтобы сделать
powershell.exe
счастливым, вам нужно \
-escape "
символов. - Примечание: PowerShell Core , кроссплатформенная версия для Windows, теперь также принимает
""
, что является наиболее надежным выбором.
Как правило, работа с цитированием и экранированием аргументов при вызове из cmd.exe
вызывает разочарование без универсальных решений, в отличие от мира Unix.К сожалению, PowerShell имеет свои проблемы, даже в мире Unix. [1]
Короче говоря: Escape-вставка "
символов.при вызове Windows PowerShell из cmd.exe
следующим образом:
Использование \""
(sic) при использовании powershell.exe -Command
, если сохранение пробела без изменений не требуется .
Этот избавляет вас от дополнительного экранирования , но пробел между \""...\""
Выполнения не сохраняются, поэтому этот метод не подходит, например, для передачи строки JSON.
- Предупреждение :
\""
не будет не работа для вызова других программ . - Пример :
powershell -command " Write-Output \""a & b\"" "
выход a & b
;то есть, хотя &
не нужно было убегать, двойные пробелы вокруг него были свернуты в одно пространство.
Использование \"
во всех остальных случаях, но тогда вам необходимо по отдельности ^
-escape следующие cmd.exe
метасимволы с ^
внутри \"...\"
выполняются: & | < > ^
Спасибо, LotPings .
Пример : powershell -command " Write-Output \"a ^& b\" "
выход a & b
;то есть &
нужно было убежать с ^
, но двойные пробелы вокруг него были правильно сохранены.
Кроме того, для обработки %
(и, с enabledelayedexpansion
, !
) буквально, синтаксис экранирования, к сожалению, зависит от того, звоните ли вы из командной строки или командного файла : используйте %^USERNAME%
(!^USERNAME
) изпервый и %%USERNAME%%
(^!USERNAME^!
/ ^^!USERNAME^^!
внутри \"...\"
бежит) от второго - см. этот ответ для подробностей кровавых.
- Само собой разумеется, что реализация вышеупомянутого является громоздкой и подверженной ошибкам задачей, которую нетривиально автоматизировать.
\"
поддерживается практически всеми программами (кроме пакетных файлов), и если это не такНе для этих дополнительных требований к экранированию, командные строки, которые используют его, могут работать на разных платформах и оболочках - с заметным исключением вызова из PowerShell , где, к сожалению, необходим дополнительный уровень экранированияи "
внутри "..."
должен быть экранирован как \`"
(sic).
См. нижний раздел для способов облегчения экранирующей боли, избегая использования "
.
Другие программы, включая PowerShell Core :
Использование просто ""
для программ, скомпилированных с помощью Microsoft компиляторов и, в Windows, также Python и Node.js , а также PowerShell Core (pwsh.exe
) .
К сожалению, эта надежная опция не работает с powershell.exe
, то есть Windows PowerShell .
Использование \"
для программ с наследием Unix, таких как Perl и Ruby - который сопровождается избегающими головными болями, рассмотренными выше.
Как избежать встроенного "
:
При этом при вызове PowerShell,вы часто можете уйти без необходимости вставлять двойные кавычки :
В вашей строке могут быть аргументы, которые невообще не нужно заключать в кавычки, например text1.txt
и text2.txt
В качестве альтернативы можно использовать одиночное -цитирование ('...'
) внутри всей командной строки,которые не требуют побега;обратите внимание, что такие строки, с точки зрения PowerShell, представляют собой строковые литералы .
Чтобы сложить все вместе:
powershell -Command "Compare-Object (Get-Content tex1.txt) (Get-Content tex2.txt) | Where-Object {$_.SideIndicator -eq '<='} | select inputobject | ft -hidetableheaders"
Примечаниечто я также удалил & { ... }
вокруг вашей команды, так как в этом нет необходимости.
[1] eryksun выглядит следующим образом: «Это неизбежное разочарование командной строки Windows. Каждая программа анализирует свою собственную командную строку, используя любые правила, которые она хочет. Поэтому синтаксис командной строки должен работать не только с оболочкой (CMD), но и со всеми вызываемыми программами.в конвейере. В мире Unix оболочка анализирует командную строку в argv
массивах, поэтому обычно вам нужно только получить правильный синтаксис, чтобы сделать оболочку счастливой. "
Проблемы с PowerShell Core, даже в Unix,проистекает из того, как он цитирует аргументы за кулисами перед их передачей - см. этот выпуск документации по GitHub .