通过批处理从 csv 文件中删除一些列和行
Removing some columns and rows from csv file via batch
我正在尝试创建一个批处理文件,该文件将编辑 .csv 并删除第一列以及文件中包含的所有摘要行。然而,我对编程批处理文件还很陌生,所以我不确定开始这个的最佳方法,如果你能包含代码如何工作的基本解释就太好了,这样我就可以 self-sustaining将来!
,Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
ABB - Egypt,,,,,,,,,,,
ElAin EL-Sokhna,,,,,,,,,,,
,Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
,Invoice,09-14-11,12005,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
ABB - Egypt - Other,,,,,,,,,,,
此文件有多个版本,因为它们来自月度报告,我需要删除第一个(空)列,以及任何看起来像 ABB - Egypt,,,,,,,,,,,
或 Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
[ 的行=18=]
所以输出应该是:
Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts,,Training Income,15000,,15000
Invoice,09-14-11,13002,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
感谢您的输入!
编辑:看来我在我的 OP 中不够清楚(抱歉,第一次来这里)。
这里有两个过程需要进行,每个文件中的第一列都必须删除,标题行 ABB - Egypt,,,,,,,,,,,
或摘要行 Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
的任何行都需要删除.
所有需要保留的行都会大部分填写,比如,Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
或者,Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
注意,和第二行一样,它们中可能存在一些缺失值,因此搜索“,”之类的内容将不起作用。
我将从这里开始学习:How can you find and replace text in a file using the Windows command-line environment?
它涵盖了从 Windows 命令行进行替换的许多细节和许多方法,有些只需要 Windows 中内置的内容,有些则需要其他可下载的软件。
Magoo 是对的,需要更多标准,但链接页面中可能有足够的信息让您克服主要障碍。
一种方法是在一个变量中定义所有规则,该变量将用于
findstr
。规则必须这样定义:
/c:"String which exclude the line" /c:"Another string which exclude the Line" /c: "etc.."
这个规则必须准确(他们不能在一行中找到谁必须留下)。
对于 empty 第一个 colonne 你可以使用我在代码中使用
的方式进行替换
,Type=Type
,Invoice=Invoice
Test.bat :
@echo off&cls
setlocal enabledelayedexpansion
Rem The rules
set $String_To_Search=/c:"ABB - Egypt," /c:"Total ElAin El-Sokhna," /c:"ElAin EL-Sokhna," /c:"ABB - Egypt - Other,"
for /f "delims=" %%a in (test.csv) do (
set $line=%%a
Rem the substitutions for the first Column
set $Line=!$Line:,Type=Type!
set $line=!$Line:,Invoice=Invoice!
Rem the test and the ouput if nothing was found
echo !$Line! | findstr /i %$String_To_Search% >nul || echo !$Line!
))>Output.csv
我使用文件 test.csv
进行测试。
输出重定向到Output.csv
也许这就是你想要的?
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (input.csv) do (
set "line=%%a"
if "!line:~0,1!" equ "," echo !line:~1!
)
当一个问题没有得到足够的解释时,我们只能猜测遗漏的细节。在这种情况下,我假设您只想要以逗号开头的行,将其删除。输出与您的输出示例相同...
编辑:添加了输出示例
Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
Invoice,09-14-11,12005,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
@ECHO OFF
SETLOCAL
(FOR /f "tokens=*delims=," %%a IN ('findstr /b /l "," q28079306.txt') DO ECHO %%a)>newfile.txt
GOTO :EOF
我使用了一个名为 q28079306.txt
的文件,其中包含您的数据用于我的测试。
产生 newfile.txt
批处理是一种用于修改文本文件的可怕语言。有很多特殊情况需要神秘的知识来解决问题。您可能有一个脚本似乎可以满足您的要求,然后您的数据中出现了一些问题,整个脚本可能需要重新设计。
关于您的具体问题,在我看来您只想保留以逗号开头的行,这意味着第一列是空的。在剩余的行中,您想要删除第一列(空列)。
假设您要保留的 none 行的第二列为空值,那么有一个非常简单的解决方案:
@echo off
>"%~1.new" (for /f "delims=, tokens=*" %%A in ('findstr "^," %1') do echo %%A)
move /y "%~1.new" %1 >nul
脚本希望文件作为第一个也是唯一的参数传递。因此,如果您的脚本名为 "fixCSV.bat",而要修改的文件是 "c:\test\file.csv",那么您将使用:
fixCSV "c:\test\file.csv"
%1
扩展为第一个参数的值,%~1
是相同的,只是它还去除了可能存在或不存在的任何封闭引号。
FINDSTR 命令读取文件并只写出以逗号开头的行。 FOR /F 命令迭代每一行输出。 "delims=, tokens=*" 选项有效地从每一行中去除所有前导逗号,结果在变量 %%A
中,然后被 ECHO。整个构造包含在括号中,标准输出被重定向到一个临时文件。最后,临时文件被移动到原始文件之上,从而替换它。
如果第 2 列可能为空,则结果将被破坏,因为它删除了所有前导逗号(在本例中为第 1 列和第 2 列)。脚本必须更复杂才能弥补。您需要设置一个变量,然后使用延迟扩展来获取子字符串,跳过第一个字符。但是延迟扩展会破坏 %%A 变量的扩展,如果它包含 !
字符。所以必须打开和关闭延迟扩展。你开始明白我说的很多特殊情况的意思了。
@echo off
setlocal disableDelayedExpansion
>"%~1.new" (
for /f "delims=" %%A in ('findstr "^," %1') do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo !ln:~1!
endlocal
)
)
move /y "%~1.new" %1 >nul
随着批处理脚本越来越复杂,它们变得越来越慢。对于大多数文件来说,这可能不是问题,但如果文件真的很大(比如数百兆字节),那么它可能会成为一个问题。
我几乎再也不用纯批处理修改文本文件了。相反,我使用我编写的名为 JREPL.BAT 的混合 JScript/batch 实用程序。该实用程序是纯脚本,可以在任何 Windows XP 以上的机器上本地运行。 JREPL.BAT 能够使用正则表达式替换有效地修改文本文件。正则表达式可能看起来很神秘,但非常值得投资学习。
假设您在 PATH 中的某处有 JREPL.BAT,那么您只需要以下命令:
jrepl "^,(.*)" "" /jmatch /f "yourFile.csv" /o -
/F 选项指定要读取的文件。
值为 -
的 /O 选项指定输出应替换原始文件。
/JMATCH 选项指定将每个替换值写出到一个新行。删除所有其他文本。
第一个参数是搜索表达式。它匹配以逗号开头的任何行,之后的所有内容都被捕获在名为 $1.
的变量中
第二个参数指定替换值,它只是变量 $1 中捕获的值。
我正在尝试创建一个批处理文件,该文件将编辑 .csv 并删除第一列以及文件中包含的所有摘要行。然而,我对编程批处理文件还很陌生,所以我不确定开始这个的最佳方法,如果你能包含代码如何工作的基本解释就太好了,这样我就可以 self-sustaining将来!
,Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
ABB - Egypt,,,,,,,,,,,
ElAin EL-Sokhna,,,,,,,,,,,
,Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
,Invoice,09-14-11,12005,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
ABB - Egypt - Other,,,,,,,,,,,
此文件有多个版本,因为它们来自月度报告,我需要删除第一个(空)列,以及任何看起来像 ABB - Egypt,,,,,,,,,,,
或 Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
[ 的行=18=]
所以输出应该是:
Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts,,Training Income,15000,,15000
Invoice,09-14-11,13002,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
感谢您的输入!
编辑:看来我在我的 OP 中不够清楚(抱歉,第一次来这里)。
这里有两个过程需要进行,每个文件中的第一列都必须删除,标题行 ABB - Egypt,,,,,,,,,,,
或摘要行 Total ElAin EL-Sokhna,,,,,,,,,241194,210400,301794
的任何行都需要删除.
所有需要保留的行都会大部分填写,比如,Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
或者,Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
注意,和第二行一样,它们中可能存在一些缺失值,因此搜索“,”之类的内容将不起作用。
我将从这里开始学习:How can you find and replace text in a file using the Windows command-line environment?
它涵盖了从 Windows 命令行进行替换的许多细节和许多方法,有些只需要 Windows 中内置的内容,有些则需要其他可下载的软件。
Magoo 是对的,需要更多标准,但链接页面中可能有足够的信息让您克服主要障碍。
一种方法是在一个变量中定义所有规则,该变量将用于
findstr
。规则必须这样定义:
/c:"String which exclude the line" /c:"Another string which exclude the Line" /c: "etc.."
这个规则必须准确(他们不能在一行中找到谁必须留下)。
对于 empty 第一个 colonne 你可以使用我在代码中使用
的方式进行替换,Type=Type
,Invoice=Invoice
Test.bat :
@echo off&cls
setlocal enabledelayedexpansion
Rem The rules
set $String_To_Search=/c:"ABB - Egypt," /c:"Total ElAin El-Sokhna," /c:"ElAin EL-Sokhna," /c:"ABB - Egypt - Other,"
for /f "delims=" %%a in (test.csv) do (
set $line=%%a
Rem the substitutions for the first Column
set $Line=!$Line:,Type=Type!
set $line=!$Line:,Invoice=Invoice!
Rem the test and the ouput if nothing was found
echo !$Line! | findstr /i %$String_To_Search% >nul || echo !$Line!
))>Output.csv
我使用文件 test.csv
进行测试。
输出重定向到Output.csv
也许这就是你想要的?
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (input.csv) do (
set "line=%%a"
if "!line:~0,1!" equ "," echo !line:~1!
)
当一个问题没有得到足够的解释时,我们只能猜测遗漏的细节。在这种情况下,我假设您只想要以逗号开头的行,将其删除。输出与您的输出示例相同...
编辑:添加了输出示例
Type,Date,Num,Name,Memo,Member,Clr,Split,Alias,Value,Balance
Invoice,09-06-10,12005,ABB - EL-Sokhna,,Accounts Receivable,,Training Income,15000,,15000
Invoice,09-14-11,12005,ABB - EL-Sokhna,“ElAin EL-Sokhna“ Trainer for OTS Application: First two weeks,Training Income,,Accounts,,150001,0
@ECHO OFF
SETLOCAL
(FOR /f "tokens=*delims=," %%a IN ('findstr /b /l "," q28079306.txt') DO ECHO %%a)>newfile.txt
GOTO :EOF
我使用了一个名为 q28079306.txt
的文件,其中包含您的数据用于我的测试。
产生 newfile.txt
批处理是一种用于修改文本文件的可怕语言。有很多特殊情况需要神秘的知识来解决问题。您可能有一个脚本似乎可以满足您的要求,然后您的数据中出现了一些问题,整个脚本可能需要重新设计。
关于您的具体问题,在我看来您只想保留以逗号开头的行,这意味着第一列是空的。在剩余的行中,您想要删除第一列(空列)。
假设您要保留的 none 行的第二列为空值,那么有一个非常简单的解决方案:
@echo off
>"%~1.new" (for /f "delims=, tokens=*" %%A in ('findstr "^," %1') do echo %%A)
move /y "%~1.new" %1 >nul
脚本希望文件作为第一个也是唯一的参数传递。因此,如果您的脚本名为 "fixCSV.bat",而要修改的文件是 "c:\test\file.csv",那么您将使用:
fixCSV "c:\test\file.csv"
%1
扩展为第一个参数的值,%~1
是相同的,只是它还去除了可能存在或不存在的任何封闭引号。
FINDSTR 命令读取文件并只写出以逗号开头的行。 FOR /F 命令迭代每一行输出。 "delims=, tokens=*" 选项有效地从每一行中去除所有前导逗号,结果在变量 %%A
中,然后被 ECHO。整个构造包含在括号中,标准输出被重定向到一个临时文件。最后,临时文件被移动到原始文件之上,从而替换它。
如果第 2 列可能为空,则结果将被破坏,因为它删除了所有前导逗号(在本例中为第 1 列和第 2 列)。脚本必须更复杂才能弥补。您需要设置一个变量,然后使用延迟扩展来获取子字符串,跳过第一个字符。但是延迟扩展会破坏 %%A 变量的扩展,如果它包含 !
字符。所以必须打开和关闭延迟扩展。你开始明白我说的很多特殊情况的意思了。
@echo off
setlocal disableDelayedExpansion
>"%~1.new" (
for /f "delims=" %%A in ('findstr "^," %1') do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo !ln:~1!
endlocal
)
)
move /y "%~1.new" %1 >nul
随着批处理脚本越来越复杂,它们变得越来越慢。对于大多数文件来说,这可能不是问题,但如果文件真的很大(比如数百兆字节),那么它可能会成为一个问题。
我几乎再也不用纯批处理修改文本文件了。相反,我使用我编写的名为 JREPL.BAT 的混合 JScript/batch 实用程序。该实用程序是纯脚本,可以在任何 Windows XP 以上的机器上本地运行。 JREPL.BAT 能够使用正则表达式替换有效地修改文本文件。正则表达式可能看起来很神秘,但非常值得投资学习。
假设您在 PATH 中的某处有 JREPL.BAT,那么您只需要以下命令:
jrepl "^,(.*)" "" /jmatch /f "yourFile.csv" /o -
/F 选项指定要读取的文件。
值为 -
的 /O 选项指定输出应替换原始文件。
/JMATCH 选项指定将每个替换值写出到一个新行。删除所有其他文本。
第一个参数是搜索表达式。它匹配以逗号开头的任何行,之后的所有内容都被捕获在名为 $1.
的变量中第二个参数指定替换值,它只是变量 $1 中捕获的值。