эхо добавляет пространство при использовании с трубой

Отвечаяэтот вопрос я нашел какое-то странное поведение, для которого у меня нет объяснения

for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echo %z^)') do @echo %a0

Вы увидите числа 10..100, теперь просто добавьте трубу, например, вsort или жеmore, без разницы:

for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echo %z^)^|sort') do @echo %a0

Будут добавлены пробелы между%a а также0! Looks like echo-ing something through a pipe adds a trailing space, it can be easily seen:

>_tempfile echo no space here
>_tempfile echo and here's a space|more

и даже

>_tempfile <nul set /p =also a space|sort

(вероятно, использует echo для печати приглашения)

Это не происходит, когда нет перенаправления вывода (в файл или для команды). Это ошибка или я что-то упустил? Как мне избавиться от места? (кроме грязного взлома последнего персонажа сvar:~0,-1)

Ответы на вопрос(2)

Решение Вопроса

Отличный и интересный вопрос (+1)

Пространство вводится конвейерным механизмом парсера CMD, а не SORT.

Когда вы выполняете команду, используя FOR / F, команда выполняется в своей собственной оболочке CMD. Кроме того, каждая сторона канала выполняется в своей собственной оболочке CMD. УвидетьПочему отложенное расширение завершается неудачно, когда внутри конвейерного блока кода? для получения дополнительной информации.

Таким образом, ваша команда на самом деле создает 3 оболочки CMD, по одной для команды FOR / F, которая, в свою очередь, создает 2 для каждой стороны канала.

Вы можете увидеть, как команды анализируются и передаются в оболочку CMD с помощью динамической переменной% CMDCMDLINE%. Поскольку мы выполняем команду из командной строки, нам нужно дважды экранировать хотя бы один символ в имени переменной, чтобы она не раскрывалась до тех пор, пока не достигнет самой внутренней оболочки CMD.

Вот команда с результатами (ведущий> моя командная строка):

>for /f "delims=" %a in ('(echo %^^^cmdcmdline%^&for /l %z in (1,1,10^) do @echo %z^)^|sort') do @echo %a0
1 0
10 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
C:\Windows\system32\cmd.exe  /S /D /c" ( echo %cmdcmdline% & FOR /L %z in (1 1 10) do @ echo %z )" 0

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

Вы можете обойти проблему, используя простой пакетный скрипт для вывода значения вместо команды ECHO.

echoArgs.bat

@echo(%*

Теперь, когда вы запустите эту команду, вы получите желаемый результат

>for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echoArgs %z^)^|sort') do @echo %a0
10
100
20
30
40
50
60
70
80
90

Другой способ обойти эту проблему - создать переменную с помощью команды ECHO и соответствующим образом избежать ее расширения.

>set [email protected](echo %z)

>for /f "delims=" %a in ('(for /l %z in (1,1,10^) do %^^^cmd%^)^|sort') do @echo %a0
10
100
20
30
40
50
60
70
80
90

EDIT

>_tempfile echo and here's a space|more Пример тоже интересный. В конце выходного файла есть дополнительное место. Но Чад Нуис прав, что ничего не сортируется из-за перенаправления левой стороны. Любая команда может быть использована с правой стороны, и результат будет таким же.

Источником проблемы по-прежнему является парсер, но способ, которым парсер реструктурирует комманду, интересен.

>>_tempfile echo %^cmdcmdline%|rem

>type _tempfile
C:\Windows\system32\cmd.exe  /S /D /c" echo %cmdcmdline% 1>_tempfile"

Обратите внимание, как перенаправление перемещается от начала до конца команды, и дескриптор файла1 явно добавлено. Вы, конечно, можете видеть, откуда берется дополнительное пространство.

 08 июн. 2012 г., 19:22
@ panda-34 - это, безусловно, другое решение.
 panda-3408 июн. 2012 г., 19:11
Ах,he that increaseth knowledge increaseth sorrow, Никогда не думал, что pipe - это больше, чем соединение stdin / stdout. Принял ваш ответ для объяснения, но не для решения. Вот простой пример:for /f "delims=" %a in ('cmd /c "for /l %z in (1,1,10) do @echo %z"^|sort') do @echo %a0
 09 июн. 2012 г., 00:07
+1, я опоздал, мне нравятся вопросы такого типа, но вы уже ответили на них своим хорошим анализом

Операторы перенаправления применяются к команде, к которой они ближе всего, а не ко всей строке.

В трех тестовых случаях вы перенаправляете стандартный выводecho а такжеset команды в файл. При перенаправлении стандартного вывода ничего не остаетсяmore или жеsort.

В вашем примере с вложенным циклом, я думаю, что есть несколько ненужных скобок, вызывающих головные боли. Попробуйте это вместо:

for /f "delims=" %a in ('for /l %z in (1,1,10^) do @echo %z^|sort') do @echo %a0
 09 июн. 2012 г., 00:56
Я вижу, к чему стремится панда-34. Паренсы необходимы, чтобы весь вывод FOR сортировался как один набор. Без паренов сортировка применяется к каждой строке в отдельности, что, конечно, ничего полезного.(this is a corrected version of my prior deleted comment)
 panda-3408 июн. 2012 г., 18:46
Вы пытались выполнить свою команду? Результаты кажутся отсортированными для вас?
 08 июн. 2012 г., 17:51
Но если вы посмотрите на содержимое _tempfile, когда оно было создано на левой стороне канала, вы увидите дополнительное пространство в конце. Как я объяснил вmy answer, парсер трубы вводит пространство. Но у вас есть верный аргумент в том, что содержимое временного файла не прошло через SORT. Ваше решение для случая FOR работает. Но могут быть случаи, когда левая сторона канала представляет собой блок команд, которые должны быть в скобках.

Ваш ответ на вопрос