设置从文本文件的每一行解析的未知数量的变量

Posted

技术标签:

【中文标题】设置从文本文件的每一行解析的未知数量的变量【英文标题】:Set An Unknown Number of Variables That areParsed From Each Line of a Text File 【发布时间】:2021-12-24 01:32:40 【问题描述】:

对于我措辞不当的问题和我的杂乱无章的工作,我深表歉意。本质上,我想。

我已经编写了批处理文件来创建指向C:\Volumes 文件夹的网络共享符号链接。

@echo off
echo:
set /p dest=ENTER FOLDER PATH: 
set dest="%dest%"
net use %dest%
if not exist "C:\Volumes" MD "C:\Volumes"
for %%i in (%dest%) do (set "fold=%%~ni")
mklink /d "c:\VOLUMES\%fold%" "%dest%"
pause

我想尝试的是相同的理论,但将脚本指向带有文件夹路径列表的文本文件mounts.txt,并让 for 循环在列表中循环为列表中的每个路径创建一个符号链接.我玩弄了计数器,但无法使其正常工作。我认为我的做法完全不对。

mounts.txt的内容

\\10.19.10.238\Masters\Removed bin\Work here
\\10.19.10.241\Scanning\WIP\to process

这不起作用:

@echo off
setlocal enableDelayedExpansion
set i=1
:add
Set /a "i+=1"
for /F "tokens=*" %%A in  (mounts.txt) do  (set dest%i%=%%A)
if exist %dest%%i% goto:add
echo %dest%
echo %dest%%i%
echo !dest!
echo !dest!%i%
pause

也不是这样:

@echo off
setlocal enableDelayedExpansion
set i=0
For /F "Tokens=1* Delims=] EOL=" %%A In ('Find /N /V ""^<"mounts.txt"') Do (
   set /a i=i+1
   set "dest!i!=%%B"
)
For /l %%a in (1,1,4) do echo _dest%%a is !dest%%a!
For /l %%a in (1,1,4) do set dest%%a=!dest%%a!
echo !dest!
pause

我确实得到了这样的东西在一定程度上可以工作,但不知道如何将dest[1]dest[2]用作脚本中其他进程中的变量。

@echo off
setlocal enabledelayedexpansion
set counter=0
for /f "tokens=*" %%a In (mounts.txt) do (
  set /a counter+=1
  set "dest[!counter!]=%%a"
)
set dest[

列表还可以添加更多。如果可以设置%dest%n变量,使用相同的理论根据每个%dest%n设置不同的%fold%变量,那么也许可以使用与原始脚本相同的过程来设置链接。

感谢任何帮助。谢谢。

【问题讨论】:

【参考方案1】:

这是一个礼貌示例,只是为了向您展示如何仍然使用 find.exe,就像在您的一个示例中一样,另外还包括一种以未知增量迭代变量的不同方法:

@Echo Off
SetLocal EnableExtensions

Rem The next line ensures that there are no variables defined with names beginning _
For /F "Delims==" %%G In ('"(Set _) 2>NUL"') Do Set "%%G="

Rem The next lines parse the directory paths content file and defines the incrementing variables
For /F "Tokens=1,* Delims=]" %%G In (
    '"%SystemRoot%\System32\find.exe /N "\" 0< "C:\Users\roar\My Directory\mounts.txt" 2>NUL"'
) Do (
    Set "_Path%%G]=%%H"
    Set "_Name%%G]=%%~nxH"
)

Rem The next lines iterate the defined variables beginning _Path[ and runs commands against them
For /F "Tokens=2 Delims=[]" %%G In ('"(Set _Path[) 2>NUL"') Do (
    SetLocal EnableDelayedExpansion
    MkLink /D "C:\Volumes\!_Name[%%G]!" "!_Path[%%G]!"
    EndLocal
)

Rem The next line undefines any previously defined variables named beginning with _
For /F "Delims==" %%G In ('"(Set _) 2>NUL"') Do Set "%%G="

请注意,您可能需要提升运行此脚本,以便 MkLink 命令创建符号链接。

【讨论】:

【参考方案2】:

您似乎希望将变量动态设置为虚拟数组并根据行号返回结果。如果是这样,请使用您创建的计数器成为 for /L 循环的最大值,这里是一个示例,只需 echoing 结果:

@echo off & set cnt=0
setlocal enabledelayedexpansion
for /F "usebackq delims=" %%i in ("mounts.txt") do (
    set /a cnt+=1
    set "var[!cnt!]=%%i"
)
for /L %%a in (1,1,!cnt!) do echo !var[%%a]!

编辑

正如@Compo 在 cmets 中强调的那样;在我们递增%cnt% 变量的初始代码块之后,我们不再需要专门在%cnt% 变量上使用delayedexpansion,因此可以使用%cnt% 而不是!cnt!

@echo off & set cnt=0
setlocal enabledelayedexpansion
for /F "usebackq delims=" %%i in ("mounts.txt") do (
    set /a cnt+=1
    set "var[!cnt!]=%%i"
)
for /L %%a in (1,1,%cnt%) do echo !var[%%a]!

【讨论】:

这是对该问题的更接近的答案,但斯蒂芬的答案是我需要的解决方案。我确实尝试过使用您的代码,虽然它确实设置了许多变量,但我不确定稍后如何在代码中使用它们。我试图做类似for %%i in (!var[%%a]!) do (set fold=%%~ni) 的事情来尝试将最终文件夹解析为变量,但这显然是不正确的。有可能是出于兴趣吗? 我对此表示赞同,因为它明智地使用了UseBackQ,并且双引号允许任何修改的列表文件名或其可能包含的路径中包含可能的问题字符。还用于从技术上展示将每个变量分配给递增变量命名方案的方法,如问题中所要求的那样。出于信息目的,我唯一要补充的一点是,这里的!cnt! (1,1,!cnt!) 不再被修改,因为它在循环之外,所以可以返回使用标准的% 字符,即(1,1,%cnt%) 谢谢,@Compo。当然,我完全同意。我在使用setlocal 时出于习惯这样做,这是基于我们在perl 中定义范围的方式,我也每天使用它,但会相应地更新答案,因为我认为未来的读者了解delayedexpansion 适合的位置很重要. @roar,虽然没有必要,但您是否尝试过在for /f 循环中创建其他变量,以便以后无需再添加for 循环。例如,将set "var[!cnt!]=%%i" 替换为两行set "spath[!cnt!]=%%i"set "sname[!cnt!]=%%~nxi"。然后您可以直接在for /l 循环中使用它们,将echo !var[%%a]! 替换为mklink /D "C:\VOLUMES\!sname[%%a]!" "!spath[%%a]!"【参考方案3】:

如果您的问题确实描述了您想要做什么,则无需设置变量。只需使用带有 for /f 循环的文本文件中的行:

for /f "delims=" %%i in (mount.txt) do mklink /d "C:\VOLUMES\%%~ni" "%%i"

引用文件名更安全,特别是如果您想要/需要使用 FQFN。因此您需要usebackq 选项,否则带引号的字符串将被处理为字符串,而不是文件名:

for /f "usebackq delims=" %%i in ("C:\full path\mount.txt") do mklink /d "C:\VOLUMES\%%~ni" "%%i"

【讨论】:

我觉得好傻。这是一个更简单的解决方案。我和for /f %%a in (mount.txt) do echo %%a 一样多,我不知道我为什么要把事情复杂化。我必须将完整路径放入 txt 文件,因为它需要以管理员身份运行。这是我的问题的答案,但不是我问的问题。非常感谢。 @roar:请看我的编辑。

以上是关于设置从文本文件的每一行解析的未知数量的变量的主要内容,如果未能解决你的问题,请参考以下文章

批处理脚本从多个文本文件的每一行计算整数(相加)

遍历文本文件并为每一行分配变量

从 RichTextBox 中的每一行获取文本?

如何将在从控制台获取的 URL 中找到的特定字符串替换为在 Ruby 文本文件中写入的每一行中找到的文件内容?

从文本文件中的 1 行设置多个变量

如何在文本文件中的每一行的开头添加序号