批处理脚本逐行读取制表符分隔的文本文件,并将一列提取到新文件

时间:2015-09-05 21:36:28

标签: arrays regex batch-file sed substring

我有导出iTunes播放列表的文本文件,这些播放列表是制表符分隔的数组。它们有27列,但为简单起见,我将在示例中包含四个:

Name    Artist  My Rating   Location
Pod1    Show1   0           E:\Podcasts\Show1\Episode99.m4a
Pod2    Show2   100         E:\Podcasts\Show2\Show2 Ep 101 - Subtitle.mp3
Pod3    Show2   60          E:\Podcasts\Show2\News 11-17-2014.aicc

等等。我只需要提取位置(始终是最后一列)并将其放在一个新的文本文件中,所以它看起来像这样:

E:\Podcasts\Show1\Episode99.m4a
E:\Podcasts\Show2\Show2 Ep 101 - Subtitle.mp3
E:\Podcasts\Show2\News 11-17-2014.aicc

以下是我迄今为止针对该目标的代码:

@ECHO OFF

type Podcasts.txt | findstr /v Grouping > Podcasts1.txt
del Podcasts.txt
rename Podcasts1.txt Podcasts.txt

虽然我已经找到了一些关于修改单行和逐行阅读文本文件的单独教程,但是我甚至难以按照我喜欢的方式修改单行,更不用说合并这两个原则了。我认为这可能是一个非常快速的答案,我只是没有找到正确的搜索。

我发现使用以下REGEX可以在Notepad ++中获得我想要的结果:

Find: .+(E\:)
Replace: \1

因此,在批处理脚本中逐行执行此操作会很有帮助。

Bonus:我正在使用生成的文件作为白名单来删除不在播放列表中的文件。如果你有一个链接或可以编写一些快速的代码,这会有所帮助。否则,我有关于我计划如何完成此操作的想法,这需要使用单个文件夹。

编辑:我发现因为有些列是空白的,所以使用它:

for /f "usebackq tokens=1-26,* delims=  " %%a in ("Podcasts.txt") do (
   echo %%q >> PodcastsTest.txt
)

有时会打错列。我需要能够搜索两个字符“E:”的东西,然后从那里开始行动,或者搜索行搜索从右到左找到第一个标签。

我刚创建的用于搜索反斜杠(当前仅出现在“位置”中)的快速而脏的方法如下:

for /f "usebackq tokens=1,* delims=\" %%a in ("Podcasts.txt") do (
    echo E:\%%b >> PodcastsTest.txt
) 

这不是一种安全的方法,因为没有什么能阻止其他字段使用反斜杠,但作为临时解决方案,它可以正常工作。

我发现Linux SED is available for Windows。也许有一种方法可以适应下面的Notepad ++ REGEX搜索?

Find: .+(E\:)
Replace: \1

3 个答案:

答案 0 :(得分:2)

这是一个新的解决方案,基于源数据的限制和问题中添加的额外信息,以及接受使用其他工具:

call jrepl ".*(E:.*)" "$1" /i /f "Podcasts.txt" /o "Podcasts2.txt"

上面的代码使用名为Jrepl.bat(dbenham)的本机Windows批处理脚本 jrepl.bat可以从以下网址下载:https://www.dropbox.com/s/4otci4d4s8x5ni4/Jrepl.bat
它也可以在这里找到:http://www.dostips.com/forum/viewtopic.php?f=3&t=6044

将其放在与批处理文件相同的文件夹中,或放在系统路径上的文件夹中。

第2部分

然后可以使用下面的代码生成一个文件,列出当前文件夹中的所有文件,这些文件不在上面的jrepl代码生成的文件中。

你提到单个文件夹 - 这样就可以处理它,并且可以在使用文件来核对文件之前对文件进行检查。

实际上,这可以与原始源文件一起使用 - 如果文件名只在文件中出现一次。

@echo off
(
for %%a in (*.*) do (
   if /i not "%%~nxa"=="%~nx0" if /i not "%%~nxa"=="Podcasts2.txt" find /i "\%%~nxa" < "Podcasts2.txt" >nul || echo del "%%a"
)
)>delfiles.bat.txt"

以下是基本解决方案,其中包含制表符分隔文件中所有单元格中的数据

如果没有该文件,我无法确定它是否具有正确的列,但该技术应该有效。

将TAB替换为编辑器中的文字制表符,该编辑器不会将TAB转换为空格,例如记事本。

@echo off
for /f "usebackq tokens=1-26,* delims=TAB" %%a in ("Podcasts.txt") do (
   echo %%b
)
pause

答案 1 :(得分:2)

这是一个纯批处理解决方案,它依赖于所需位置始终以E:\开头(不区分大小写)的假设,并且该字符串不得出现在任何早期列中:

@echo off
setlocal disableDelayedExpansion
>"Podcasts.txt.new" (
  for /f "usebackq skip=1 delims=" %%A in ("Podcasts.txt") do (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    echo !ln:*E:\=E:\!
    endlocal
  )
)

如果您知道没有位置包含!,那么您只需在顶部启用延迟扩展一次,然后从循环中删除SETLOCAL和ENDLOCAL。

正则表达式是获取最后一列的好方法,无论内容如何。批处理的一个好的正则表达式实用程序是JREPL.BAT - 一个基于纯脚本的实用程序(混合JScript /批处理),它可以在XP之后的任何Windows机器上本机运行。

以下JREPL单线程运行良好:

jrepl "[^\t]+$" $0 /jmatch /jbegln "skip=(ln==1)" /f "Podcasts.txt" /o "Podcasts.txt.new"

这是另一个JREPL解决方案:

jrepl ".*\t" "" /a /jbegln "skip=(ln==1)" /f "Podcasts.txt" /o "Podcasts.txt.new"

注意 - 如果在批处理脚本中使用JREPL解决方案,则必须使用CALL JREPL。

最后一个正则表达式可以用于sed:

sed "1d;s/.*\t//" "Podcasts.txt" >"Podcasts.txt.new"

答案 2 :(得分:1)

用sed和几个假设

PathTocygwin/sed -e '\#.*[[:blank:]]\([A-Z]:/.*$# !d' -e 's//\1/' Podcasts.txt > Podcasts1.txt
del Podcasts.txt
rename Podcasts1.txt Podcasts.txt

这里的假设 - 路径正在使用映射驱动器 - 1到25列中没有以前的路径 - 仅保留与模式对应的行