标题: [文本处理] 新人学习,文本替换 [打印本页]
作者: zydrawer 时间: 2018-2-6 16:12 标题: 新人学习,文本替换
本帖最后由 zydrawer 于 2018-2-6 19:52 编辑
先贴码:
@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%a in (findfile.txt)do (
set /a num=0
set h1=%%a
echo %%a
for /f "tokens=1,2 delims= " %%i in (key.txt)do (
set h2=!h1:%%i=%%j!
if !h1! neq !h2! (
echo !h2! >>d.txt
)else (
if !num! == 0 (
echo !h2! >>d.txt
set /a num = num+1
))
))
set num=
pause
目的:查找关键字并将其替换为指定字符串
有两个文本文档.txt findfile.txt key.txt
key.txt是关键字文本有两列 之间是与tab键隔开,形式如下
第一列 第二列
11111 aaaaa
222222 bbbbbbbb
pppp cccccccc
。。。 。。。。
findfile.txt 文件是待查找文件 这个文件的内容中是含有key.txt文件中第一列的关键字
找到第一列的关键字后用第二列的字符串替换掉第一列的关键字
其他不变,然后将结果输出到另一个文件中
问题:
我写的bat处理命令虽将字符串替换成功,但是也将没有替换的行也重复输出了,
花了好久时间也没有找到原因,拜托各位前辈大神了
作者: 523066680 时间: 2018-2-6 19:58
劝退:换其他脚本语言吧。
作者: zydrawer 时间: 2018-2-6 20:36
回复 2# 523066680
你这打击新人的积极性么
作者: yhcfsr 时间: 2018-2-7 02:37
- if !h1! neq !h2! (
- echo !h2! >>d.txt
- )else (
- if !num! == 0 (
- echo !h2! >>d.txt
- set /a num = num+1
- )
复制代码
根据你这段,如果存在没有被替换的行,必然会输出且只会输出首次没有被替换的行。
作者: /zhqsystem/zhq 时间: 2018-2-7 04:34
本帖最后由 /zhqsystem/zhq 于 2018-2-7 04:38 编辑
- for /f "tokens=1,* delims=tab分割符" %%i in ('type key.txt')do (
- set "#="
- for /f "delims=" %%k in ('type findfile.txt')do if /i "%%i"=="%%k" set "#=y"
- if defined # (
- echo,%%jtab分割符%%j
- )else (
- echo,%%itab分割符%%j
- )
- )
复制代码
作者: zydrawer 时间: 2018-2-7 09:57
回复 5# /zhqsystem/zhq
首先感谢答主热心解答。
关于答主的if /i "%%i"=="%%k" 有些不解,
可能是我描述问题不清楚,之前没有对findfile.txt进行说明
findfile.txt只是包含有key.txt中第一列的关键字,也就是说关键字只是findfile.txt中每一行的子串,关键字位置并不在行首
所以我认为这里不应该用等号吧
作者: zydrawer 时间: 2018-2-7 10:05
回复 4# yhcfsr
感谢指出不足指出
我运行后的结果是,无论有没有替换,它都会输出原行(未经替换的行),若是存在替换的过程,他会在打印原行之后再次打印替换后的行(这个先后循序,然我感到很迷惑,就像是先执行了else语句后再执行if语句)
而我要求是:若不存在要替换的关键字,则直接打印输出,若存在,则只打印输出替换后的行
作者: zydrawer 时间: 2018-2-7 10:09
再次看到4楼5楼的回复时间,再次感谢
作者: yhcfsr 时间: 2018-2-7 16:12
本帖最后由 yhcfsr 于 2018-2-7 16:21 编辑
从你整个代码来看,执行逻辑是这样的:
先读取源文本某行(假设行号为x),再读取关键字文本(假设总共有n行)。
如果读关键字文本第一行时,x行中没找到需要替换的“11111”关键字,就输出原行;如果找到“11111”,就替换再输出替换后的行。
如果在读取关键字文本第一行进行了替换操作,那你的判定条件“h1 neq h2”恒成立,也就是说从在读取关键字文本第二行开始,如果有替换就输出替换后的x行,如果没有替换,就重复输出上一次被替换后的x行内容。总共输出n次x行。
如果在读取关键字文本第一行没有进行替换操作,输入一次x行的原行后,不会再输出x行的原行。假设读取关键字文本第m行开始进行首次替换操作,判定条件“h1 neq h2”恒成立,之后会输出x行(n-m)次,加上第一行输出的原行,共输出(n-m+1)次x行。
所有对于源文本的任何一行,都有可能输出多次。
我想你的目的应该是源文本中的任何一行,对关键字文本进行检索替换后,只输出一次。要实现这个目的,要在读取完关键字文本所有行进行的替换操作后,再输出该行。
作者: /zhqsystem/zhq 时间: 2018-2-7 19:21
本帖最后由 /zhqsystem/zhq 于 2018-2-7 19:31 编辑
回复 6# zydrawer
这是整行完整对比[多个空格都会对比失败],如果有对比成功则激活输出替换,如果没有则原始输出
以下是每句的解释
rem解释只限本行,在看不懂我也没办法,对于新学有难度
for /f "tokens=1,* delims=tab分割符" %%i in ('type key.txt')do (rem:加载主文本
set "#="&&rem:标记清空
for /f "delims=" %%k in ('type findfile.txt')do if /i "%%i"=="%%k" set "#=y"&rem:加载对比数据,当主文本指定=任意行内的数据则标记变量
if defined # (rem:存在标记则有数据相等
echo,%%jtab分割符%%j
)else (rem:不存在标记则没有数据相等
echo,%%itab分割符%%j
)
)
作者: slore 时间: 2018-2-8 00:01
回复 523066680
你这打击新人的积极性么
zydrawer 发表于 2018-2-6 20:36
花了好久时间没有解决,说明这个事用批处理不方便,如果自己需要解决问题,而不是学习批处理,完全没有必要死磕批处理。
1.楼主用了2层for循环,每一行替换把key.txt要重新读取一边,效率低。
2.要使用延时变量,搞得代码变量使用要注意,对新手,基础不是很好的话,明明自己思路对的但是代码却不是按自己想的走。
3.如果KEY.TXT里面有某些特殊字符,set h2=!h1:%%i=%%j!的方式替换,导致语法错误出错,不能解决楼主问题。
如果把批处理当解决问题工具的话,有其他东西能简单搞定也愿意使用的话,文本,字符串处理交给别的脚本语言是正确的,系统自带的VBS也行,不过代码多些。
比如楼主的问题,用ruby脚本语言,不使用特殊用法刻意减少代码行数,纯粹按最简单的逻辑处理,使用基本语法,不到10行还简单明白。- text = File.read('findfile.txt') #读取全部内容保存到text变量
- kvlist = File.read('key.txt') #读取key.txt文件内容
- kvlist.each_line do |line| #并按行循环
- line = line.chomp #去掉末尾\r\n换行符
- if line.length > 0 #不是空行的话
- kv = line.split("\t") #Tab #按Tab分割得到KEY,VALUE数组
- text.gsub!(kv[0], kv[1]) #替换内容
- end
- end
- File.write('findfile_2.txt', text)
复制代码
问题:
我写的bat处理命令虽将字符串替换成功,但是也将没有替换的行也重复输出了,
花了好久时间也没有找到原因,拜托各位前辈大神了
zydrawer 发表于 2018-2-6 16:12
批处理很简单,一行一行走,查看每行的数据和自己的预期是否一致就能找出问题。
简单的调试方法:
findfile.txt只写简单的2行,key.txt先写2行。
abc def 123 456 777
abc 888 456 123
33 ccc
456 xxx
然后把echo off改成echo on,自己在cmd下运行看每行执行的结果,尤其是在输出文件前,可以自己echo单独看看。
echo xxx > b.txt => echo xxx b.txt
另外,大体一看有2处不是很明白,
if !h1! neq !h2!
为什么要判断替换后是否相同?
abc def 123 456 777找不到33没有替换为ccc那么它还是abc def 123 456 777,直接输出就行。
abc def 123 456 777再找到456替换为abc def 123 xxx 777,直接输出,为什么要判断找到与否?
if !num! == 0 (
为什么要记录替换次数?一行只替换一次么?比如abc 33 456的话,只把33替换为ccc,456就不再替换为xxx了是么?描述的需求里面没有体现。
作者: yhcfsr 时间: 2018-2-8 19:46
- @echo off
- set "SrcFile=F:\Test\findfile.txt"
- set "KeyFile=F:\Test\key.txt"
-
- for /f "delims=" %%a in ('findstr /n .* "%SrcFile%"') do (
- set "var=%%a"
- setlocal enabledelayedexpansion
- set var=!var:*:=!
- if "!var!" neq "" for /f "usebackq tokens=1,2 delims= " %%i in ("%KeyFile%") do set "var=!var:%%i=%%j!"
- (echo.!var!)>>"%SrcFile%.log"
- endlocal
- )
- pause&exit
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |