Board logo

标题: 条件文本文件替换[已解答] [打印本页]

作者: 123cainiao     时间: 2007-9-23 23:21    标题: 条件文本文件替换[已解答]

有2个TXT文件:ab.txt  和 cd.txt
ab.txt文件内容如下:
姓名"张三",ID'102' ,tel'0102211',0,25,11
姓名"李似答",ID'102' ,tel'0202211',0,25,11
姓名"王二",ID'102' ,tel'01023311',0,25,11
........

cd.txt文件内容如下:
赵括
王彬
李铃
.......

可否用批处理命令来完成从cd.txt文件每行提取名字来替换ab.txt文件中的每行的姓名内容.做到最后生成的ab.txt文件如下:
姓名"赵括",ID'102' ,tel'0102211',0,25,11
姓名"王彬",ID'102' ,tel'0202211',0,25,11
姓名"李铃",ID'102' ,tel'01023311',0,25,11
........

[ Last edited by 123cainiao on 2007-9-25 at 01:36 PM ]
作者: yoyodos     时间: 2007-9-24 11:03
感觉有点困难,哈,我再看看
作者: 123cainiao     时间: 2007-9-24 11:09
在论坛上搜索相关内容,发现一个可以参考的文章:现摘抄如下:

文本编辑(逐行替换 AB文本融合)

文件名: A.txt
内容如下:
old("A")new("A")
old("A")new("A")
old("A")new("A")
old("A")new("A")
old("A")new("A")
...

文件名: B.txt
内容如下:



...

要把A逐行替换成
old("好")new("好")
old("坏")new("坏")
old("差")new("差")
....

参考的答案:
@echo off & setlocal enabledelayedexpansion
set data=old("A")new("A")
for /f "tokens=* " %%i in (b.txt) do (
            set data=!data:A=%%i!
            echo !data!>>c.txt
            set data=!data:%%i=A!
           )
pause

但是上面的显然不能处理我提的问题,主要是替换的格式不同,还请大家帮助!
作者: yoyodos     时间: 2007-9-24 11:12
恩,不太一样,因为你那个文件要求每个字符串都要替换,不是统一的替换,优点难度,哈哈,我看能不能编出来啊
作者: wudixin96     时间: 2007-9-24 11:41

@echo off
setlocal enabledelayedexpansion
for /f "tokens=1* delims=:" %%a in ('findstr /n .* ab.txt') do (
  for /f "tokens=1* delims=:" %%i in ('findstr /n .* cd.txt^|find "%%a:"') do set str=%%j
  set ln=%%b
  call set string=%%ln:"=#%%
  call set string=%%string:"=#%%
  for /f "tokens=2 delims=#" %%i in ("!string!") do set str1=%%i
  call :js
)
pause
goto :eof

:js
set ln=!ln:%str1%=%str%!
echo %ln%

作者: yoyodos     时间: 2007-9-24 11:52
学习啊!哈够厉害
作者: 123cainiao     时间: 2007-9-24 12:07
非常感谢wudixin96
着实让人大开眼界。
作者: yoyodos     时间: 2007-9-24 12:11
这个又是必须用call来实现的吧,不然替换变量里没办法赋值,是吧?
问wudixin96一个问题啊,call set string=%%ln:"=#%% 前面的call是什么意思呢?
谢谢!
作者: lxmxn     时间: 2007-9-24 12:12    标题: 我也来玩下Awk版的


gawk -F[\"|"] "BEGIN{OFS=\"\"}{if(FNR==NR){str[NR]=$0} else { a+=1; $2=\"\x22\" str[a] \""\"; print $0}}" cd.txt ab.txt

作者: yoyodos     时间: 2007-9-24 12:14
彻底晕倒。。。。。
作者: wudixin96     时间: 2007-9-24 12:15
那个call有起到延迟的作用,这个论坛里用的人蛮多的。

看到第三方工具的方便了吧??o(∩_∩)o...哈哈
作者: yoyodos     时间: 2007-9-24 12:23
俺还需要学习,哈哈。再问个问题呀,下面双百分号起什么作用?
call set string=%%ln:"=#%%
不好意思刚来论坛里面混,谢谢
作者: wudixin96     时间: 2007-9-24 12:25
就是配合call起到延迟作用的啊,先搜索一下吧,我的表达能力很差,说不清楚
作者: yoyodos     时间: 2007-9-24 12:30
谢谢,我查查
作者: 123cainiao     时间: 2007-9-24 12:51
请教,我经过测试发现,在DOS屏幕上实现了修改内容显示,而ab.txt文件文件依然无更新.
即最终没有实现生成新的ab.txt文件?
作者: yoyodos     时间: 2007-9-24 13:00
很容易了,把echo 变量 改为echo 到文件就行了
作者: 123cainiao     时间: 2007-9-24 13:02


  Quote:
Originally posted by yoyodos at 2007-9-24 01:00 PM:
很容易了,把echo 变量 改为echo 到文件就行了

 呵呵,谢谢你.我明白了.
作者: yoyodos     时间: 2007-9-24 13:08
一起学习。。哈哈
作者: yoyodos     时间: 2007-9-24 15:01
我也贴一个,哈哈
@echo off
setlocal enabledelayedexpansion
cd.>tmp.txt
set /a x=0

for /f "tokens=1 delims=姓名," %%r in (ab.txt) do echo %%r>>tmp.txt
for /f "delims=" %%a in (ab.txt) do (
    set /a x+=1
    set str=%%a
    for /f "tokens=1* delims=:" %%h in ('findstr /n "." tmp.txt') do (
        set n1=%%h
            if !n1!==!x! (
                set replaced=%%i
        )
    )
    for /f "tokens=1* delims=:" %%m in ('findstr /n "." cd.txt') do (
        set n2=%%m
            if !n2!==!x! (
                set new="%%n"
            )
    )
    call :replace
)
del /q tmp.txt
pause

:replace
    set str=!str:%replaced%=%new%!
    echo !str!
[ Last edited by yoyodos on 2007-9-24 at 03:02 PM ]
作者: 123cainiao     时间: 2007-9-24 15:51


  Quote:
Originally posted by yoyodos at 2007-9-24 03:01 PM:
我也贴一个,哈哈
[code]
@echo off
setlocal enabledelayedexpansion
cd.>tmp.txt
set /a x=0

for /f "tokens=1 delims=姓名," %%r in (ab.txt) do echo %%r>>tmp.txt
fo ...

总体来说主要有2个关键点值得学习
1、是 "tokens=1 delims=“的用法,这一点很多时候非常容易弄错
2、是变量替换提取

如果ab.txt的内容由原来的:
姓名"张三",ID'102' ,tel'0102211',0,25,11
姓名"李似答",ID'102' ,tel'0202211',0,25,11
姓名"王二",ID'102' ,tel'01023311',0,25,11
........


变成如下:
abcd rster_www_er 姓 名 "张三",ID'102' ,tel'0102211',0,25,11
abcd rster_www_er 姓 名 "李似答",ID'102' ,tel'0202211',0,25,11
abcd rster_www_er 姓 名 "王二",ID'102' ,tel'01023311',0,25,11
....


那么以上的参考答案代码都需要做适当的修改。
从这里可以知道,如果是编辑一个通用性强的代码,最好能够采用模糊查找定位的方法,比如本例,即使ab.txt文件每行的长度和里面其它内容变化,只要含有
[姓 名 "王二"]这样的字段,就可以查到,并替换.
请问是否可以实现?
作者: yoyodos     时间: 2007-9-24 16:10
不太明白你的意思,
思路就是将每一行字符串的  “姓名” 替换成 "abcd rster_www_er 姓 名"
是不是就可以呢?
哈哈
作者: 123cainiao     时间: 2007-9-24 16:40


  Quote:
Originally posted by yoyodos at 2007-9-24 04:10 PM:
不太明白你的意思,
思路就是将每一行字符串的  “姓名” 替换成 "abcd rster_www_er 姓 名"
是不是就可以呢?
哈哈

不是的,我的意思是作为通用性强的搜索语句,采用模糊定位查找,比采用按照分割符号来查找的方式更加实用。
比如最开始的ab.txt文件里的内容:
姓名"张三",ID'102' ,tel'0102211',0,25,11
姓名"李似答",ID'102' ,tel'0202211',0,25,11
姓名"王二",ID'102' ,tel'01023311',0,25,11
这是非常工整的
要是不工整的,变为:
abcd rster_www_er 姓 名 "张三",ID'102' ,tel'0102211',0,25,11
abcd ,er 姓 名 "李似答",ID'102' ,tel'0202211',0,25,11
abcd rster,www,r 姓 名 "王二",ID'102' ,tel'01023311',0,25,11
这样的格式,严格以分割符查找的设计思路,几乎用不成,而采用模糊查找才能实现。
总的来说就是无论你每行文字变成什么样,[姓 名 "张三"]在每行任何不同位置变换,都能实现替换功能。

[ Last edited by 123cainiao on 2007-9-24 at 04:43 PM ]
作者: yoyodos     时间: 2007-9-24 17:18
晕,以姓名作分隔符不就行了吗
在delims=后面写姓名,姓 名,姓  名。。。。就能得到后面的名字了啊
作者: 123cainiao     时间: 2007-9-24 18:49


  Quote:
Originally posted by yoyodos at 2007-9-24 05:18 PM:
晕,以姓名作分隔符不就行了吗
在delims=后面写姓名,姓 名,姓  名。。。。就能得到后面的名字了啊

谢谢你回答,经过反复测试,做了适当调整,可以了。
你的代码适用性能是非常好的。再次感谢!
作者: terse     时间: 2007-9-24 19:13
我也来一段学习
@echo off
setlocal enabledelayedexpansion
     set mn=0
     for /f "tokens=1* delims=," %%i in (ab.txt) do (
     set data=%%i%%j
     set /a mn+=1
     for /f "tokens=1* delims=:" %%a in ('findstr /n .* cd.txt') do (
     if !mn! EQU  %%a    set data=!data:%%i=姓名"%%b",!
)
echo !data!>>c12.txt
)
pause
作者: 123cainiao     时间: 2007-9-25 13:25


  Quote:
Originally posted by terse at 2007-9-24 07:13 PM:
我也来一段学习
@echo off
setlocal enabledelayedexpansion
     set mn=0
     for /f "tokens=1* delims=," %%i in (ab.txt) do (
     set data=%%i%%j
     set /a mn+=1
     for  ...

以上所有回复的参考答案中terse给的适应性能最强,可以不加修改完全适应通用性文件的查找替换,只许需要把 姓名 字段替换为你要查找的即可.
谢谢terse
作者: 123cainiao     时间: 2007-9-25 13:43    标题: 问题的延伸,看看下面的情况会用到很多

如果把问题延伸,比如ab.txt文件只有这么一行
姓名"张三",ID'102' ,tel'0102211',0,25,11
现在cd.txt文件还是不变:
赵括
王彬
李铃
。。。。。
可否做到从ab.txt文件里替换第一行后的姓名后,直接可以复制这种格式,生成一个完全和cd.txt文件行数一致的文件ef.txt:
姓名"赵括",ID'102' ,tel'0102211',0,25,11
姓名"王彬",ID'102' ,tel'0102211',0,25,11
姓名"李铃",ID'102' ,tel'0102211',0,25,11
........

这里问题就不单单是对等行替换了,需要涉及复制,想来还是会复杂一些。
作者: terse     时间: 2007-9-25 14:23
@echo off
setlocal enabledelayedexpansion
     for /f "tokens=1* delims=," %%i in (ab.txt) do (
     set data=%%j
)
     for /f "tokens=1* delims=:" %%a in (cd.txt) do (
>>c12.txt echo 姓名"%%a",!data!
)
pause
作者: yoyodos     时间: 2007-9-25 14:29
terse回答的很好呀,哈,123cainiao还有问题没??我也练练
作者: 123cainiao     时间: 2007-9-25 16:37


  Quote:
Originally posted by yoyodos at 2007-9-25 02:29 PM:
terse回答的很好呀,哈,123cainiao还有问题没??我也练练

呵呵,谢谢各位回答,不同的程序表达方式,达到相同的目的,值得好好研究.
   顺祝大家中秋快乐,合家幸福!
作者: 123cainiao     时间: 2007-9-25 19:15    标题: 仔细研究发现,还可以把问题作如下改动:

ab.txt文件的内容如下:
[abcd]
doorCount = 1
goodpaIp = 127.0.0.1:8383
Max = 125
tackmoneys = 127.0.0.1:8086
doorCounttc = 12
doorCountwkl= 18
doorCountasd = 20

cd.txt文件内容如下:

[abcd]=
goodpaIp_name= goodip
tackmoneys_0=127.128.225.18
doorCounttc = 8
doorCountwkl= 185
doorCountasd = 20

现在可否从cd.txt文件里提取127.128.225.18来更新ab.txt文件
新生成的ab.txt文件为:
[abcd]
doorCount = 1
goodpaIp = 127.128.225.18:8383
Max = 125
tackmoneys = 127.128.225.18:8086
doorCounttc = 12
doorCountwkl= 18
doorCountasd = 20

请注意:127.128.225.18这个的位数先假设是变动的,也就是说即使他变成12.11.23.11或者其余位数的ip,都能实现完整替换。
.
作者: terse     时间: 2007-9-25 21:23
@echo off
setlocal enabledelayedexpansion
ren ab.txt ab1.txt
for /f "tokens=1,2,3 delims==:" %%i in ('type cd.txt^|find /i "tackmoneys"') do set data=%%j
for /f "tokens=1,2,3 delims==: " %%i in ('type ab1.txt^|find /i "goodpaIp"') do set data1=%%j
for /f "tokens=1,2,3 delims==: " %%i in ('type ab1.txt^|find /i "tackmoneys"') do set data2=%%j
if !data! equ !data1! if !data! equ !data2! goto :eof
for /f "tokens=* delims==: " %%i in (ab1.txt) do (
    set m=%%i
    set m=!m:%data1%=%data%!
    set m=!m:%data2%=%data%!
echo !m! >>ab2.txt
)
ren ab2.txt ab.txt
pause
作者: yoyodos     时间: 2007-9-26 00:58
我来贴个复杂的。。。
@echo off
cd.>new.txt
setlocal enabledelayedexpansion
set m=0
set a=0
set b=0
set cd_name=tackmoneys_0
set ab_name1=goodpaIp
set ab_name2=tackmoneys
for /f "delims=" %%i in (cd.txt) do (
    call :cdcd %%i
)
for /f "delims=" %%y in (ab.txt) do (
    call :abab %%y
)
for /f "delims=" %%y in (ab.txt) do (
    set str=%%y
    set str=!str:%ab_result1%=%cd_result%!
    set str=!str:%ab_result2%=%cd_result%!
    echo !str!>>new.txt
)

:abab
    if "%1" == "" exit /b
    if "%a%" == "1" (
        set ab_result1=%1
        for /f "tokens=1,2 delims=:" %%i in ("!ab_result1!") do set ab_result1=%%i
        set a=0
        exit /b
    )
    if "%b%" == "1" (
        set ab_result2=%1
        for /f "tokens=1,2 delims=:" %%i in ("!ab_result2!") do set ab_result2=%%i
        set b=0
        exit /b
    )
    if "%1" == "%ab_name1%" set a=1
    if "%1" == "%ab_name2%" set b=1
    shift
    goto abab

:cdcd
    if "%1" == "" exit /b
    if "%m%" == "1" (
        set cd_result=%1
        set m=0
        exit /b
    )
    if "%1" == "%cd_name%" set m=1
    shift
    goto cdcd

pause
123问题好多啊。,哈哈

[ Last edited by yoyodos on 2007-9-26 at 01:00 AM ]
作者: 123cainiao     时间: 2007-9-26 10:54


  Quote:
Originally posted by terse at 2007-9-25 09:23 PM:
@echo off
setlocal enabledelayedexpansion
ren ab.txt ab1.txt
for /f "tokens=1,2,3 delims==:" %%i in ('type cd.txt^|find /i "tackmoneys"') do set data=%%j
for /f "tokens ...

这段程序,反复测试,发现存在一个问题:
程序第一次运行,会生成一个ab1.txt和ab.txt里文件的参数一致,替换成功。
随便修改一下cd.txt里的值,再重新运行程序(不删除前次生成的ab1.txt)
发现提示文件重复,这时会生成ab2.txt,而且只有ab2.txt替换成功,ab.txt和ab1.txt均无变化。
再次修改一下cd.txt里的值,再重新运行程序(不删除前次生成的ab1.txt和ab2.txt)

结果程序提示文件重复,新的替换值以整体累加的形式出现在ab2.txt文件里,其余文件无替换。
作者: 123cainiao     时间: 2007-9-26 10:56


  Quote:
Originally posted by yoyodos at 2007-9-26 12:58 AM:
我来贴个复杂的。。。
[code]
@echo off
cd.>new.txt
setlocal enabledelayedexpansion
set m=0
set a=0
set b=0
set cd_name=tackmoneys_0
set ab_name1=goodpaIp
set ab_name2=tackmone ...

这段程序虽然复杂的多,但经过反复测试,均表现正常!
作者: yoyodos     时间: 2007-9-26 11:04
terse写的没错拉,ab1.txt ab2.txt都是临时文件,每次删除了就ok了。呵呵
作者: yoyodos     时间: 2007-9-26 11:10
terse是通过特殊字符找ip的,我那个是通过指定的字符串的位置找ip的,思路不同罢了。
^_^
作者: terse     时间: 2007-9-26 11:27


  Quote:
Originally posted by 123cainiao at 2007-9-26 10:54:

这段程序,反复测试,发现存在一个问题:
程序第一次运行,会生成一个ab1.txt和ab.txt里文件的参数一致,替换成功。
随便修改一下cd.txt里的值,再 ...

ab1.txt 只是原ab.txt的备份而已 可以去掉这一步
或者这样试一下
@echo off
setlocal enabledelayedexpansion
cd.>ab2.txt
for /f "tokens=1,2,3 delims==:" %%i in ('type cd.txt^|find /i "tackmoneys"') do set data=%%j
for /f "tokens=1,2,3 delims==: " %%i in ('type ab.txt^|find /i "goodpaIp"') do set data1=%%j
for /f "tokens=1,2,3 delims==: " %%i in ('type ab.txt^|find /i "tackmoneys"') do set data2=%%j
if !data! equ !data1! if !data! equ !data2! goto :eof
for /f "tokens=* delims==: " %%i in (ab.txt) do (
    set m=%%i
    set m=!m:%data1%=%data%!
    set m=!m:%data2%=%data%!
echo !m! >>ab2.txt
)
del ab.txt
ren ab2.txt ab.txt
pause
作者: 123cainiao     时间: 2007-9-26 13:06


  Quote:
Originally posted by terse at 2007-9-26 11:27 AM:

ab1.txt 只是原ab.txt的备份而已 可以去掉这一步
或者这样试一下
@echo off
setlocal enabledelayedexpansion
cd.>ab2.txt
for /f "tokens=1,2,3 delims==:" %%i in ( ...

测试完毕,程序完全正常!
谢谢回复!
以上所有参考答案,仔细研究,融会贯通,完全可以解决类似文本字符串替换的其他问题。再次感谢所有回帖网友!
作者: yoyodos     时间: 2007-9-26 15:03
123继续出题呀.哈哈
作者: yyf0346     时间: 2007-9-26 16:32
我是菜鸟,刚来,我想请教一下各位,如何根据用户在窗口中输入的值来把指定文件中的某一字符串给替换掉。
比如有一个a.sql文件,和b.bat文件在同一个目录内,a.sql文件内有段内容:
EXECUTE @ReturnCode = msdb.dbo.sp_add_job @job_id = @JobID OUTPUT , @job_name = N'预定检查', @owner_login_name = N'localhost\Administrator', @description = N'没有可用的描述。', @category_name = N'[Uncategorized (Local)]', @enabled = 1, @notify_level_email = 0, @notify_level_page = 0, @notify_level_netsend = 0, @notify_level_eventlog = 2, @delete_level= 0
. . . . . . .

如何写b.bat文件,把其中的localhost换成用户输入的一个字符串;
又比如有一个INI文件夹里有一个a.INI文件,内容如下:
[CONNECT_DB]
CONNECTSTRING="Provider=SQLOLEDB.1;Password=MTIzNDU2;Persist Security Info=True;User ID=SA;Initial Catalog=HXGL_DB;Data Source=localhost\SQLEXPRESS1"
LatestLogin=admin
. . . . . .

此INI文件夹和b.bat不在一个目录结构内,要把localhost\SQLEXPRESS1换成用户输入的字符该怎么办?
我知道和用户交互是 SET /P char=请输入字符串:
那么怎么把这个用户输入的字符串按照上边的想法操作呢?我是在公司应用的,有谁能帮帮我啊?在此先谢谢大家了!
作者: yyf0346     时间: 2007-9-26 16:41
没人回答我啊?555555
我是菜鸟,大家都照顾点............
等待中。。。。。。。。。
作者: wudixin96     时间: 2007-9-26 16:54
不是不回答,这种问题,请先搜索论坛,实在没有再提问吧
作者: terse     时间: 2007-9-26 16:56
@echo off
setlocal ENABLEDELAYEDEXPANSION
set  str1=localhost\SQLEXPRESS1
SET /P STR2=输入替换字符
for /f "delims=" %%i in (路径\a.ini) do (
    set str=%%i
    set str=!str:%str1%=%str2%!
echo !str!>>路径\b.ini
)
pause
作者: yyf0346     时间: 2007-9-26 18:03
:D
谢谢多谢以及不甚感谢!,由于刚来,有很多地方都不是很明白,可能我问的问题论坛里都有了,以后我会先查找论坛资源再发问的了,还请多多关照了....
作者: shim     时间: 2007-9-26 21:20
高手真多啊,学习中。