批处理之家's Archiver

batman 发表于 2008-9-10 16:50

【练习-023】按要求替换文本字符的批处理

前言:
  本人最近眼睛出了毛病,所以不能常在论坛和群里为大家服务了,在此深表遗憾,也请
大家予以谅解。
  今天帮同事解决了一个工作上的小问题,觉得这个问题比较有代表性,所以整理了下出
了这题(个人无法在excel表格中完成操作,不知有高人能否做到)。
出题目的:
  唯一的目的在于通过解题灵活掌握字符替换技巧
加分原则:
  1 思路新颖基分5分
  2 代码高效基分4分
  3 代码简洁基分3分
  4 代码通用基分2分
  5 无临时文件基分1分
  6 完美代码加15分
题目如下:
  有a.txt内容如下(在实际中有数万行)[code]330001--330002--330106
330001--330006--330108
330001--330007--330112
330101--330108--330205
330101--330110--330212
330201--330211--330301
330302--330304--330309
330302--330308--330402
330302--330410--330408
330402--330406--330411
330505--330511--330807[/code]  要求用批处理对字符进行逐行替换,将其中的330**替换为200*年*月,但不允许
出现05月(正确为5月)字样,同时输出如下:[code]2000年1月--2000年2月--2001年6月
2000年1月--2000年6月--2001年8月
2000年1月--2000年7月--2001年12月
2001年1月--2001年8月--2002年5月
2001年1月--2001年10月--2002年12月
2002年1月--2002年11月--2003年1月
2003年2月--2003年4月--2003年9月
2003年2月--2003年8月--2004年2月
2003年2月--2004年10月--2004年8月
2004年2月--2004年6月--2004年11月[/code]

[[i] 本帖最后由 batman 于 2008-9-24 08:03 编辑 [/i]]

pusofalse 发表于 2008-9-10 17:01

BATMAN兄多注意休息,一切安好。
另想问一下,文本中有无类似于330125--330125--330125这样的数据
即330之后的125,要替换为2012年5月--2012年5月--2012年5月吗?
还是说表示月份的后两个数字一定leq 12?

[[i] 本帖最后由 pusofalse 于 2008-9-10 17:30 编辑 [/i]]

pusofalse 发表于 2008-9-10 19:40

先来抛砖,拿来献丑了,看下是否是这样的输出:[code]@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%a in (a.txt) do (
      set "str=%%a"&set "var="
      set "str=!str:330=200!"
      for /f "tokens=1-3 delims=-" %%i in ("!str!") do (
           set/a i=%%i,j=%%j,k=%%k
           for %%s in (i j k) do (
                set "c=!%%s:~-2!"
                if "!c!" neq "10" set "c=!c:0=!"
                set "var=!var!!%%s:~,4!年!c!月--"
           )
           echo !var:~,-2!
))
echo.&pause[/code]在excel表格中操作,我也不知如何完成,对OFFICE一窍不通,求教高人。

[[i] 本帖最后由 pusofalse 于 2008-9-10 19:43 编辑 [/i]]

随风 发表于 2008-9-10 20:26

版主保重身体[code]@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%a in (a.txt) do (
   set "str=%%a"
   set str=!str:-= !&set "str=!str:330=200!"
   for %%i in (!str!) do (
     set "var=%%i"
     set /a num=100!var:~-2!%%100
     set "ok=!ok!--!var:~0,4!年!num!月"
)
    echo !ok:~2!
    set "ok="
)
pause[/code]

batman 发表于 2008-9-11 08:06

我的方案

利用shift移位:[code]
@echo off
for /f "tokens=1,2* delims=-" %%i in (a.txt) do set "s=%%k"&call :lp %%i %%j %%k   
pause>nul&goto :eof
:lp
set "str=%1"
set "a=%str:~3,1%"&set /a b=1%str:~-2%%%100
set "var=%var%--200%a%年%b%月"
if "%1" neq "%s%" shift&goto lp
echo %var:~2%&set "var="
[/code]

[[i] 本帖最后由 batman 于 2008-9-11 08:10 编辑 [/i]]

batman 发表于 2008-9-11 13:03

&&这题真的不难,不知大家为什么不愿尝试呢?本版块的出题环节一直在继续中,但个人
觉得并没有达到预期的效果,具体表现在:基本上都是几个版主和技术人员在解答题目,却
鲜见其他会员跟贴解题。
  于是,个人有所反省,是不是这样的题目超越了大多数会员的能力范围了?是不是这样
的题目并不具有代表性?是不是这样的题目脱离实际太远了?是不是大家不能接受这样的学
习形式?
  为了加强论坛学习指导的针对性,还请大家畅所欲言,就你所认为的,论坛应从哪些方
面出发来引导和提高大家学习批处理,来提出自已的建议;我们将根据大家的建议,不断完
善论坛的学习功能,健全学习机制,以达到共同提高的最终目的。

[[i] 本帖最后由 batman 于 2008-9-11 13:08 编辑 [/i]]

huahua0919 发表于 2008-9-11 13:07

这些数据是在Excle中的吗.斑竹是否能够上传这个文件来看看
我对Excle小有研究。也许能够解决

batman 发表于 2008-9-11 21:47

[quote]原帖由 [i]huahua0919[/i] 于 2008-9-11 13:07 发表 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=9979&ptid=1793][img]http://www.bathome.net/images/common/back.gif[/img][/url]
这些数据是在Excle中的吗.斑竹是否能够上传这个文件来看看
我对Excle小有研究。也许能够解决 [/quote]
兄弟可以直接把a.txt的内容复制到execel中进行处理啊。。。

bater 发表于 2008-9-11 22:03

我用excle的解决方案

在空白单元里输入公式[code]=LEFT(REPLACE(A1,1,3,200),4)&"年"&RIGHT(A1,2)&"月"[/code]然后按照内容多少把数据全部选中后,全部数据转换成下列:
  

2000年01月 2000年02月 2001年06月 2000年01月  2000年06月 2001年08月


然后把数据全部选中,右键选择复制-->选择性粘贴-->选择数值,这样就把单元格的公式属性去掉了
选择编辑菜单下的,替换 输入 "年0" 全部替换为 "年",就得到你要的数据了!

这是用函数方法完成,用vba的方法也可以完成,也是用到for循环,和批处理的方法类似!

[[i] 本帖最后由 bater 于 2008-9-11 22:34 编辑 [/i]]

batman 发表于 2008-9-12 07:57

[quote]原帖由 [i]bater[/i] 于 2008-9-11 22:03 发表 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=10009&ptid=1793][img]http://bbs.bathome.net/images/common/back.gif[/img][/url]
在空白单元里输入公式=LEFT(REPLACE(A1,1,3,200),4)&"年"&RIGHT(A1,2)&"月"然后按照内容多少把数据全部选中后,全部数据转换成下列:
  

2000年01月 2000年02月 2001年06月 2000年01月  200 ... [/quote]
本人实是愚钝,照兄弟所述的在excel中搞了半天,硬是不得法,没有成功转换,汗。。。

本人也摸索了一个公式:=MID(B1,1,4)&"年"&MID(B1,5,2)&"月"&"--"&MID(B1,9,4)&"年"&MID(B1,13,2)&"月"&"--"&MID(B1,17,4)&"年"&MID(B1,21,2)&"月",基本上能达到替换的要求了。。。

[[i] 本帖最后由 batman 于 2008-9-12 08:42 编辑 [/i]]

bater 发表于 2008-9-12 09:11

呵呵,是我没有读懂题目,我首先把你A.txt的 数据利用
替换把-- 换成空格  ,然后由excel的数据导入进去
所以得到的数据,是没有--的,又看了下题目正如你说的用&把“--”是可以的,总之,我的excle老师告诉我,在excle下能得到正确答案,就是好的,因为,效率已经比
手动修改,提高很多了.
另外,在论坛学习了你很多的p处理知识。希望能从你身上学到更多的知识!

batman 发表于 2008-9-12 09:39

[quote]原帖由 [i]bater[/i] 于 2008-9-12 09:11 发表 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=10031&ptid=1793][img]http://bbs.bathome.net/images/common/back.gif[/img][/url]
呵呵,是我没有读懂题目,我首先把你A.txt的 数据利用
替换把-- 换成空格  ,然后由excel的数据导入进去
所以得到的数据,是没有--的,又看了下题目正如你说的用&把“--”是可以的,总之,我的excle老师告诉我,在 ... [/quote]
兄弟太客气了,呵呵,咱们一起学习,共同进步了。

zhangmi 发表于 2008-9-15 07:12

我在excel中用分列去掉--,然后用公式=LEFT(REPLACE(A1,1,3,200),4)&"年"&(RIGHT(A1,2)*1)&"月",向右向下一拉就成了。

keen 发表于 2009-5-19 21:12

[code]@echo off&setlocal enabledelayedexpansion
for /f %%i in (a.txt) do (
    set str=%%i&set str=!str:--= !&set "v="
    for %%j in (!str!) do (
        set var=%%j&set var=!var:330=200!
        set var1=!var:~0,4!
        if "!var:~-2,1!" equ "0" (set var2=!var:~-1,1!) else (set var2=!var:~-2,2!)
        set v=!v!!var1!年!var2!月--
      
)
echo !v:~0,-2!
)
pause[/code]

keen 发表于 2009-5-19 21:17

发现跟pusofalse版主在三楼的一样了!

keen 发表于 2009-5-19 21:34

回复 5楼 的帖子

shift用法妙,但call :lp进行循环,效率可能不高吧!

netbenton 发表于 2009-5-19 23:13

::要想高效,利用变量定义,尽量减少循环体内的代码!
[code]
@echo off&setlocal enabledelayedexpansion
for /l %%a in (3300,1,3315) do (
set #a=%%a
for /l %%b in (1,1,9) do (set %%a0%%b=20!#a:~2,2!年%%b月)
        for %%b in (10 11 12) do (set %%a%%b=20!#a:~2,2!年%%b月)
)
for /f "tokens=*" %%a in (a.txt) do (
    for /f "tokens=1-3 delims=-" %%b in ("%%a") do (echo !%%b!--!%%c!--!%%d!)
)
echo.&pause

[/code]

keen 发表于 2009-5-20 00:05

回复 17楼 的帖子

netbenton兄的想法实在是妙,效率也高,但是付出了内存的代价!
如果这样的数很多,占用内存会很大。

netbenton 发表于 2009-5-20 07:38

当然,如果数很多占用内存就多,
就本题而言,仅仅为:年数*12而已,就算是跨100年,也不过1200个变量定义。
在具体使用时,就要看实际情况了,如果“定义体”比“循环体”要大,则不应该使用变量定义。

zhouyongjun 发表于 2009-6-13 13:59

[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=1-3 delims=-" %%a in (a.txt) do (
    set/a y1=%%a/100,y1-=1300,m1=%%a%%100,y2=%%b/100,y2-=1300,m2=%%b%%100,y3=%%c/100,y3-=1300,m3=%%c%%100
    echo !y1!年!m1!月--!y2!年!m2!月--!y3!年!m3!月
)
pause[/code]

tab 发表于 2009-6-13 17:20

sed s/330/200/g;s/--/\n/g a.txt|sed "s/200./&年/;s/$/月/;s/年0/年/"|sed N;N;s/\n/--/|sed N;s/\n/--/
其实允许2009年01月形式的话,会少很多代码而且格式也工整。

curious 发表于 2009-6-13 21:11

我这代码效率不高,仅能做对而已[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=1-3 delims=--"  %%i in (a.txt) do (
call :aa %%i
call :aa %%j
call :aa %%k
echo !b:~2!
set b=
)
pause>nul
goto :eof
:aa
set a=%1
set a=!a:330=200!
set a1=!a:~0,4!年
set a2=!a:~-2!
if !a2! lss 10 (set a2=!a2:~-1!) else (set a2=!a2:~-2!)
set a=!a1!!a2!月
set b=!b!--!a![/code]

lengmoke 发表于 2021-10-13 10:20

[code]
@echo off
setlocal EnableDelayedExpansion
for /f %%i in (a.txt) do (
    set str=%%i
    set str=20!str:~2,2!年!str:~4,2!月--20!str:~10,2!年!str:~12,2!月--20!str:~18,2!年!str:~20,2!月
    echo !str:年0=年!
)
[/code]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.