проблема с powershell и cmd с трубами - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть эта команда, которая работает нормально на powershell

Compare-Object (Get-Content "tex1.txt") (Get-Content "tex2.txt") | Where-Object{$_.SideIndicator -eq "<="} | select inputobject |  ft -hidetableheaders

Я пытаюсь запустить в cmd, выполнив это:

powershell -Command " & {Compare-Object (Get-Content "tex1.txt") (Get-Content "tex2.txt") | Where-Object{$_.SideIndicator -eq "<="} | select inputobject |  ft -hidetableheaders}"

, но она говорит что-то вроде: имя, каталог или синтаксис тома неверен (на испанском языке, поэтому я не знаю точного перевода)

Я думаю, что проблема в каналах, так как запуск всего перед конвейером: Compare-Object (Get-Content "tex1.txt") (Get-Content "tex2.txt") работает

PD: Я также пытался написать ^ перед каналами, но мне не удалось.

1 Ответ

0 голосов
/ 27 сентября 2018

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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...