从批处理文件中以逗号分隔的列表中删除重复项



我有一个批处理文件,它(除其他外(将列表变成这样:

'foo_ph1-1.tif', 'foo_ph2-1', 'foo_ph2-2'

在一个名为INVNOS:的局部变量中

'fooph1', 'fooph2', 'fooph2'

我想从第二个列表中删除重复项。当我创建列表时,从这个问题的答案来看,我一直在尝试这样做,但没有成功。

以下是我的清单。

@echo off
setlocal ENABLEDELAYEDEXPANSION
for %%f in ("*.tif") do @echo %%~nf>>list.lst
set FNAMES=
set INVNOS=
for /f %%i in ('type list.lst') do (
set FNAMES=!FNAMES!'%%i.jpg', 
for /f "tokens=1 delims=-" %%a in ("%%i") do (
set BEFORE_HYPHEN=%%a
set INVNOS=!INVNOS!'!BEFORE_HYPHEN:_=!', 
) 
)
set "FNAMES=%FNAMES:~0,-2%" 
set "INVNOS=%INVNOS:~0,-2%"
echo %INVNOS%
endlocal

使用findstr的解决方案不起作用,因为我需要用一个空字符串初始化INVNOS,并且我被%和"!"之间的差异所困扰,以及在for循环内进行切片。

我知道这在Python中很容易,但我想使用本机(Windows 10/Windows Server(,所以CMD或Powershell。

有什么建议吗?

为了描绘更大的画面,INVNOS(库存编号(是从充满tif的目录中派生的,因此我们可以检查它们是否存在于某些sql数据库中。

我会以不同的方式处理这个问题:

@echo off
setlocal ENABLEDELAYEDEXPANSION
for %%f in (*.tif) do (
for /f "delims=-" %%g in ("%%~nf") do set "~%%g=."
)
for /f "delims=~=" %%a in ('set ~') do set "INVOS='%%a', !INVOS!"
set "INVOS=%INVOS:~0,-2%
echo %INVOS:_=%

诀窍是为每个文件名定义变量(variableNAMES包含文件名。一个变量只能存在一次,因此根据定义,没有重复(

使用另一个for循环,从定义的变量中提取名称并将它们连接起来。下划线可以一次性删除,而不是从每个子字符串中删除。

需要时,可以使用for /f "delims==" %%a in ('set ~') do set "%%a="删除变量,但脚本结束时,这些变量将被销毁。(当你想确定时,同一行,在你设置之前,没有意外定义以~开头的变量(

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: The values assigned to these variables suit my system and test environment
SET "sourcedir=u:your files"
SET "tempfile=%temp%tempfile.txt"
:: remove variables starting :
FOR  /F "delims==" %%a In ('set : 2^>Nul') DO SET "%%a="
(for %%f in ("%sourcedir%*.tif") do echo %%~nf)>"%tempfile%"
set "FNAMES="
set "INVNOS="
for /f "usebackqdelims=" %%i in ("%tempfile%") do (
set FNAMES=!FNAMES!'%%i.jpg', 
for /f "tokens=1 delims=-" %%a in ("%%i") do (
set "BEFORE_HYPHEN=%%a"
SET "before_hyphen=!BEFORE_HYPHEN:_=!"
IF NOT DEFINED :!BEFORE_HYPHEN! set "INVNOS=!INVNOS!'!BEFORE_HYPHEN:_=!', "&SET ":!BEFORE_HYPHEN!=Y"
) 
)
set "FNAMES=%FNAMES:~0,-2%" 
set "INVNOS=%INVNOS:~0,-2%"
echo %INVNOS%
IF DEFINED tempfile DEL "%tempfile%"
GOTO :EOF

您需要更改分配给sourcedir的值以适应您的情况。该列表使用了适合我的系统的设置。

我故意在名称中包含空格,以确保空格得到正确处理。

%tempfile%是临时使用的,是您选择的文件名。

usebackq选项是必需的,因为我选择在源文件名周围添加引号。

SO的标准做法是对字符串使用语法set "var=value"这样可以确保忽略行上的杂散尾随空格。

for ... %%a循环中OP代码set INVNOS...上的邪恶尾随空格。

给定OP的原始文件名列表foo_ph1-1.tif foo_ph2_1 foo_ph2-2,处理应该产生fooph1 fooph21 fooph2,而不是声称的fooph1 fooph2 fooph2

我的测试包括foo_ph2-2.tif

代码本质上是相同的,但首先根据爱尔兰原则清除启动:的任何环境变量。

指定的临时文件被重新创建,避免了首先删除它的(未实现的(要求。

在应用if not defined测试之前,显式删除BEFORE_HYPHEN的下划线。我选择:是因为:不能是文件名的一部分。一旦将名称应用于invnos列表,就会建立:!BEFORE_HYPHEN!变量,以防止重复的BEFORE_HYPHEN值进一步累积到invnos中。

如果您想升级到PowerShell,可以在.bat文件脚本中完成类似的操作。当然,如果这些都是在PowerShell中编写的,那么编写和维护会更容易。

===doit.bat

@ECHO OFF
FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
"(Get-ChildItem -File -Filter '*.tif' |" ^
"ForEach-Object { '''' + $($_.Name.Split('-')[0].Replace('_','')) + '''' } |" ^
"Sort-Object -Unique) -join ','"') DO (
SET "INVNOS=%%~A"
)
ECHO INVNOS is set to %INVNOS%
EXIT /B

Get-ChildItem生成目录中所有*.tif文件的列表。Split((做的是";delims=-";在FOR循环中执行。[0]下标选择文件名中第一个"-"字符之前的所有内容。替换将删除"_"字符。排序对象删除的重复项以生成唯一列表。join将名称列表转换为单个逗号分隔的字符串。生成的字符串存储在INVNOS变量中。

你真的希望在列表中的每个名字周围都有APOSTROPHE字符吗?

最新更新