Пакетный файл, не загружаемый в переменную [duplicate]

Уже есть много ответов, которые расскажут вам, как сделать правильную копию, но никто из них не говорит, почему ваша оригинальная «копия» не удалась.

Python не сохраняет значения в переменных; он связывает имена с объектами. Ваше исходное назначение взяло объект, на который ссылается my_list, и связал его с new_list. Независимо от того, какое имя вы используете, остается только один список, поэтому изменения, сделанные при обращении к нему как my_list, будут сохраняться при обращении к нему как new_list. Каждый из других ответов на этот вопрос дает вам различные способы создания нового объекта для привязки к new_list.

Каждый элемент списка действует как имя, поскольку каждый элемент связывается не исключительно с объектом. Неглубокая копия создает новый список, элементы которого привязываются к тем же объектам, что и раньше.

new_list = list(my_list)  # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]

Чтобы сделать копию списка еще на один шаг, скопируйте каждый объект, на который ссылается ваш список, и привяжите эти копии элементов в новый список.

import copy  
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]

Это еще не глубокая копия, потому что каждый элемент списка может ссылаться на другие объекты, точно так же, как список привязан к его элементам. Чтобы рекурсивно скопировать каждый элемент в списке, а затем каждый другой объект, на который ссылаются каждый элемент, и т. Д .: выполните глубокую копию.

import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)

Для получения дополнительной информации о копировании в окне [gg] см. документацию .

39
задан Tarc 3 September 2014 в 20:53
поделиться

3 ответа

Посмотрите на следующие примеры ...

Пример 1: Следующий код НЕ использует задержанное расширение, поэтому переменные в цикле for расширяются только один раз. Это означает, что %Count% всегда будет расширяться до 0 в каждой итерации цикла, независимо от того, что мы делаем с ним с помощью команды set:

@echo off
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=%COUNT% + 1
  echo Count = %COUNT%
)
pause

Итак, этот скрипт выведет:

Count = 0
Count = 0
Count = 0
Count = 0

Это не значит, что этот цикл должен работать.

Пример 2: С другой стороны, если мы используем задержанное расширение, мы имеем следующий скрипт, который будет работать как ожидаемый.

setlocal ENABLEDELAYEDEXPANSION
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=!COUNT! + 1
  echo Count = !COUNT!
)

pause

и, как ожидается, он выведет:

Count = 1
Count = 2
Count = 3
Count = 4

Когда вы используете ENABLEDELAYEDEXPANSION и разворачиваете переменную, используя ! вместо %, переменная повторно расширяется каждый раз, и все работает так, как предполагается.

48
ответ дан carlossierra 21 August 2018 в 00:18
поделиться
  • 1
    Хорошие примеры. Но еще лучше использовать set /A COUNT=COUNT + 1 или более короткий set /A COUNT+=1, чтобы продемонстрировать, что в пределах арифметического выражения переменные могут ссылаться только на их имена. Арифметическое выражение является строкой после set /A. Вывод справки при запуске в окне командной строки set /? объясняет задержку расширения на примере IF и FOR , а также специальный анализ переменных в арифметических выражениях. – Mofi 8 September 2017 в 13:55

Я хотел добавить отличный пример того, как «EnableDelayedExpansion» (EDE) может быть полезен вне вездесущих примеров цикла FOR.

Вот строка данных землетрясения, которую я хочу проанализировать (I назовите это 1line.txt)

ak_11574812 2015.04.29.193822 62.9525 -148.8849 1.0 9.5 1 49km S Кантуэлл, Аляска

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

ECHO OFF
setlocal enableDelayedExpansion
set where=72
set /p line=<1line.txt
set locate=!line:~%where%,28!
echo %locate%

EDE позволяет мне помещать переменную (где) внутри другой переменной (строки). EDE сначала преобразует переменную с квадратом в%, а затем обработает переменную, заключенную в скобки! и (в этом случае) выталкивают результаты в переменную «locate».

7
ответ дан Bruce Sinkula 21 August 2018 в 00:18
поделиться
  • 1
    Хотя это не было напрямую связано с вопросом, это было единственное место, где я смог узнать, как удалить подстроки, передав переменные, и какой правильный порядок! И% был, так что спасибо :) – Lee Winder 9 January 2016 в 23:19

Ответ Макса дает пример того, где пакетный скрипт будет действовать по-разному с или без замедленного расширения .

Для полноты давайте ответьте на другую часть вопроса и покажите ситуацию, когда вы не захотите использовать задержанное расширение, когда ваши данные содержат восклицательный знак ! (и показывают два способа обработки таких данных):

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion

  set "_auxFile=%temp%\%~n0.txt"
  rem create multiline sample file
  >"%_auxFile%" ( for /L %%G in (1,1,3) do echo line %%G is 100%% valid! Sure! Hurrah!)
  rem create one-line sample file
  >"%_auxFile%" echo this line is 100%% valid! Sure! Hurrah!

  echo(
  echo --- file content 
  type "%_auxFile%"

  echo(
  SETLOCAL EnableDelayedExpansion
    echo --- enabled delayed expansion chokes down unescaped exclamation marks^^^! "^!"
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%~G"
      echo loop var=%%~G
      echo _auxLine=!_auxLine!
    )
  ENDLOCAL
  echo(
  SETLOCAL DisableDelayedExpansion
    echo --- toggled delayed expansion works although might be laborious!
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%G"
      echo loop var=%%G
      SETLOCAL EnableDelayedExpansion
        echo _auxLine=!_auxLine!
      ENDLOCAL
    )
  ENDLOCAL
  echo(
  SETLOCAL DisableDelayedExpansion
    echo --- keep delayed expansion DISABLED: use CALL command!
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%G"
      echo loop var=%%G
      call :ProcessVar
    )
  ENDLOCAL

  rem delete the sample file
  del "%_auxFile%"
ENDLOCAL
goto :eof

:ProcessVar
  echo _auxLine=%_auxLine%
  echo WARNING: neither !_auxLine! nor %%G loop variable is available here!  
goto :eof

Обратите внимание, что в приведенном выше сценарии показано правильные способы экранирования

  • % знак процента с помощью %%, удвоение его (замедленное расширение не имеет значения) и
  • ! восклицательный знак, если включено замедленное расширение: "^!", если оно заключено в пару двойных кавычек, затем используйте общий escape-символ cmd и командный скрипт ^; ^^^! в противном случае используйте три ^ кармана.

Выход:

==> D:\bat\SO\10558316.bat

--- file content
this line is 100% valid! Sure! Hurrah!

--- enabled delayed expansion chokes down unescaped exclamation marks! "!"
loop var=this line is 100% valid Hurrah
_auxLine=this line is 100% valid Hurrah

--- toggled delayed expansion works although might be laborious!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!

--- keep delayed expansion DISABLED: use CALL command!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!
WARNING: !_auxLine! as well as %G loop variables are not available here!

==>
8
ответ дан Community 21 August 2018 в 00:18
поделиться
  • 1
    +1 только для этой средней секции и ссылки; Я искал эту информацию с тех пор, как я вышел из матки. – Andrew 28 October 2017 в 04:21
Другие вопросы по тегам:

Похожие вопросы: