Board logo

标题: [文本处理] [已解决]批处理怎样实现文本替换? [打印本页]

作者: fanfande    时间: 2011-5-21 11:24     标题: [已解决]批处理怎样实现文本替换?

下面是txt文档里面的内容,很有规律:

<a title="搜狐" href="http://www.sohu.com">搜狐</a>
<a title="百度" href="http://www.baidu.com">百度</a>
<a title="网易" href="http://www.163.com">网易</a>

想把他变成下面的格式,并生成在另外一个文档里面:
搜狐,http://www.sohu.com,1
百度,http://www.baidu.com,1
网易,http://www.163.com,1

顺祝大家周末愉快!
作者: CrLf    时间: 2011-5-21 11:45

  1. @echo off
  2. (for /f "tokens=3,5 delims==> " %%a in (1.txt) do for /f "tokens=1,2" %%c in ("%%~a %%~b") do echo %%c,%%d,1)>2.txt
复制代码

作者: applba    时间: 2011-5-21 14:31

我看直接用引号分割就够了吧。
作者: Hello123World    时间: 2011-5-21 14:32

  1. @echo off
  2. (for /f "tokens=3,5 delims==> " %%a in (test.txt) do  echo %%~a,%%~b,1)>2.txt
  3. pause>nul
复制代码
一层for就能解决了,为什么还要嵌套呢?
作者: CrLf    时间: 2011-5-21 14:39

3# applba
delims不能用引号作为分隔符

4# Hello123World
这个确实忘了,因为原先是分两步的,简化后忘了统一起来。
作者: CrLf    时间: 2011-5-21 14:44

呀,回帖时忽然有了个猜想,验证下竟然真的可以,看来可以推翻delims不能用"作为分隔符的观点了:
  1. @echo off
  2. for /f tokens^=1*^ delims^=^" %%a in ("sd"z"vc") do echo %%b
  3. pause
复制代码

作者: Hello123World    时间: 2011-5-21 14:53

本帖最后由 Hello123World 于 2011-5-21 14:59 编辑

1.为什么你的条件引号都没有也能行?
2.结果是z"vc  ,这说明"并不是真的作为分隔符在起作用。结果2是我错了,*会连同分隔符一起显示。
作者: Hello123World    时间: 2011-5-21 14:54

delims不能用"作为分隔符,估计是产生了语法错误,用^似乎也没法让"起作用。
作者: CrLf    时间: 2011-5-21 15:04

1.为什么你的条件引号都没有也能行?
2.结果是z"vc  ,这说明"并不是真的作为分隔符在起作用。结果2是我错了,*会连同分隔符一起显示。
Hello123World 发表于 2011-5-21 14:53

1,以前一直惯性思维,没想过引号是的真实目的,我想for可能只能读取一个参数,而""就是把多个参数合并成一个参数的媒介,同时兼具转移作用,避免=被当成语句中的分隔符,所以就去掉引号,用转义来达到它的效果
2,没细看我的代码吗?
作者: CrLf    时间: 2011-5-21 15:05

耶,我终于也有技术创新了...
作者: Hello123World    时间: 2011-5-21 15:06

  1. @echo off
  2. (for /f tokens^=2^,4^ delims^=^" %%a in (test.txt) do echo %%a,%%b,1)>2.txt
  3. pause
复制代码
应用一下,用"作为分隔符来解决楼主的问题。
作者: fanfande    时间: 2011-5-22 00:16

谢谢大家!顺祝大家工作顺利!
作者: applba    时间: 2011-5-22 08:09

10# zm900612


兄弟啊,我是随便说说的呀,没有考虑到这么多的
作者: fengyun530    时间: 2011-5-22 11:03

各位大大能解释一下这句吗?
(for /f tokens^=2^,4^ delims^=^" %%a in (test.txt) do echo %%a,%%b,1)>2.txt
一般看到的都是
for /f "tokens=1,delims=" 变量 in(文件名) do echo 变量
但是在这里怎么多加了2个符号 tokens^=2^,4^ delims^=^"这段代码该如何理解呢。感觉有点不好理解,望做个较详细的讲解,谢谢!
作者: fengyun530    时间: 2011-5-22 11:04

主要就是不理解。为什么要多加^这个。tokens=2不就得了。为何要加这个符号"^"。
作者: plp626    时间: 2011-5-22 12:40

不错,以前我也是惯性思维,没留神过。只知道

for /f .... ('命令') do 。。。
中若命令含有等号,逗号,时,要给等号,等号,分毫加^转义。。。我就想这个是cmd另启动的进程把命令作为参数列表再次传给cmd处理。。。

所以一直用for /f .... (' "命令" ') do 。。。省事多了,,没再深入,看来。。。
这个for 可以看做cmd的函数了,delims tokens 不过是它的参数列表。。。这样就容易理解=, 空格不被双引号括起来就得^转义传递参数了
作者: CrLf    时间: 2011-5-22 12:48

各位大大能解释一下这句吗?
(for /f tokens^=2^,4^ delims^=^" %%a in (test.txt) do echo %%a,%%b,1)>2.txt
一般看到的都是
for /f "tokens=1,delims=" 变量 in(文件名) do echo 变量
但是在这里怎么多加了2个 ...
fengyun530 发表于 2011-5-22 11:03



我的理解是(马后炮...)习惯上为for /f命令的各种参数加引号是为了转义“=”、“ ”等会被误认为分隔符的参数内容,for /f可能只能接受一个参数,所以useback可以不加引号:
for /f useback %%a in ("te st.txt") do echo %%a
但是却不能与其他参数不使用"来直接联用,而且其他带=或其他有分隔符意义字符的参数若不用"或者^来转义就直接使用,运行时“tokens=1,4”会被cmd理解成“tokens 1 4”,这当然会出错,但是我们可以通过用^转义的方法来代替引号的作用,原理就像
“for /f %%a in ('dir /b^|sort') do echo %%a”
等同于
“for /f %%a in ('"dir /b|sort"') do echo %%a”
一样。
作者: CrLf    时间: 2011-5-22 12:50

而且利用for /f的特性也可以实现变量延迟哦:
  1. @echo off
  2. (
  3. echo %random%
  4. for /f %%a in ('echo %%random%%') do echo %%a
  5. pause
  6. )
复制代码
这是for /f的运行机制决定的
作者: applba    时间: 2011-5-25 06:19

本帖最后由 applba 于 2011-5-25 07:22 编辑

我觉得
引号有转义所有特殊字符(除%)的作用,大多数时候用来转义空格。
for /f后面的一串option,使用引号主要就是为了转义空格和等号,防止预处理时空格和等号作为分隔符分割多个组合的option。
这两个引号在for /f运行的时候会被丢掉,引号中的option在执行时被解释。

既然用双引号是为了转义空格等字符,自然使用^也是可以转义空格和其他特殊字符的。
一般来说只要转义了空格和等号,使用^和双引号效果是一样的。
当然双引号更简单,但是如果涉及到双引号本身做分隔符就必须使用^。

下面是测试,1.txt的内容
  1. abcde^fg^
  2. abcd"efg"
  3. abc^de"fg
  4. abc"de^fg
复制代码
  1. @echo off
  2. ::^做分隔符的两种写法
  3. echo "^做分隔符的写法1"
  4. for /f "tokens=1-3delims=^" %%i in (1.txt) do echo %%j
  5. echo "^做分隔符的写法2"
  6. for /f tokens^=1-3delims^=^^ %%i in (1.txt) do echo %%j
  7. ::"做分隔符的写法
  8. for /f tokens^=1-3delims^=^" %%i in (1.txt) do echo %%j
  9. ::下面的写法提示“命令语法不正确 ”
  10. ::for /f "tokens=1-3 delims="" %%i in (1.txt) do echo %%j
  11. ::"和^一起做分隔符
  12. for /f tokens^=1-3delims^=^"^^ %%i in (1.txt) do echo %%j
复制代码
有人弄出来%做分隔符的情形吗?
作者: CrLf    时间: 2011-5-25 12:22

19# applba

以百分号为分隔符要考虑到预处理的因素:
... delims=%% ...
作者: techon    时间: 2011-5-25 23:25

本帖最后由 techon 于 2011-5-25 23:27 编辑

转义字符的确有不少妙用

在某些命令中 几乎所有字符都可以被转义处理
  1. @echo off
  2. echo 123%%456%%789>1.txt
  3. echo 123"456"789>>1.txt
  4. echo 123^&456^&789>>1.txt
  5. for /f tokens^=1-3^,*delims^=^%%^&^"^2 %%i in (1.txt) do @echo ---%%i---%%j---%%k---%%l
  6. pause
复制代码
回车,手动换行被转义处理
  1. set a=101
  2. if "!a:~0,1!"=="0" (echo a0===0&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
  3.                                                                                else echo a2===1) ^
  4.                                                else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
  5.                                                                                else echo a2===1) ^
  6.                else echo a0===1&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
  7.                                                                                else echo a2===1) ^
  8.                                                else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
  9.                                                                                else echo a2===1
  10. rem 规范格式
  11. set a=110
  12. if "!a:~0,1!"=="0" (
  13.   echo a0===0
  14.   if "!a:~1,1!"=="0" (
  15.     echo a1===0
  16.     if "!a:~2,1!"=="0" (
  17.       echo a2===0
  18.     ) else (
  19.       echo a2===1
  20.     )
  21.   ) else (
  22.     echo a1===1
  23.     if "!a:~2,1!"=="0" (
  24.       echo a2===0
  25.     ) else (
  26.       echo a2===1
  27.     )
  28.   )
  29. ) else (
  30.   echo a0===1
  31.   if "!a:~1,1!"=="0" (
  32.     echo a1===0
  33.     if "!a:~2,1!"=="0" (
  34.       echo a2===0
  35.     ) else (
  36.       echo a2===1
  37.     )
  38.   ) else (
  39.     echo a1===1
  40.     if "!a:~2,1!"=="0" (
  41.       echo a2===0
  42.     ) else (
  43.       echo a2===1
  44.     )
  45.   )
  46. )
  47. pause&goto :EOF
复制代码

作者: fanfande    时间: 2011-11-24 12:10

回复 2# CrLf


    我对tokens 感觉理解有点乱啊
作者: CrLf    时间: 2011-11-24 14:08

回复 22# fanfande


    详见《[系列教程]批处理for语句从入门到精通[20101225更新]》:http://bbs.bathome.net/thread-2189-1-1.html
tokens 是以 delims 指定的字符集为分隔符,对输入的单行或多行内容进行划分,并取在 tokens 中指定的第 n 节,而其后引用的参数则收 tokens 影响,如果要用令牌(%%a、%%b 等)对指定的某几节进行选取,必须在 tokens 中声明改节位置。
    比如:
  1. for /f %%a in ("测试 test") do echo %%%%a=%%a   %%%%b=%%b
  2. ::在for 中除了 usebackq 和 skip 外所有开关均有默认参数,上面这句貌似啥也没设置,其实默认为:"eol=; tokens=1 delims=[tab制表符][空格]"
  3. ::而因为在隐藏的默认参数中,tokens 仅指定了 1,所以只分配第一节内容给了 %%a,而没有分配任何内容给 %%b
  4. for /f "tokens=1,2,4-5 delims=诗《》:" %%a in ("唐诗经典:(插入广告)《长恨歌》白居易") do echo 由 %%a 代诗人 %%d 所著的 %%c 是一部 %%b 。
  5. ::delims 指定了四个分隔符,tokens 以此为据,指定要取第1、2、4、5 节
  6. ::这里的 1,2 表示第 1 和 2 节,而 4-5 表示 4 到 5 节(在取连续多节的时候是很有效的简写,此处仅为示例)
  7. ::而要注意的是,因为此处未在 tokens 中指定第 3 节,故 %%c 跳过第三节,直接与已被声明的第 4 节对应,%%d 则紧随其后,与第 5 节对应。
  8. for /f "tokens=2* delims=-" %%a in ("当前日期-北京时间-2011-11-24") do echo %%b
  9. ::tokens 中 * 除非是唯一参数,否则必须跟在某个数字后面,以声明其位置。
  10. ::在 tokens 中指定了某一节后我们可以不引用它,但是他会占用一个对应位置的令牌
  11. for /f "tokens=* delims=0" %%a in ("000001234000") do echo %%a
  12. ::将第一节与其后内容作为一个整体,去掉前缀的所有分隔符 0
  13. ::"tokens=*" 与 "delims=" 的区别就在于此,前者将删除第一节之前的所有分隔符取其后内容,而后者则是不指定分隔符所以整行文本作为一节内容输出。
复制代码
需要注意的是,tokens 的范围从 1~32,其中能明确指定第几节的是 1~31 节,第 32 个只能是 *,无法一次性取得。
我们写在 in 前面的那个令牌代表所取的第一节,其后令牌往下类推,比如当第一个令牌为 %%a 时,第 2-3 节为 %%b 和 %%c,当第一个令牌被设为 %%b 时,第 2-3 节为 %%c 和 %%d,依此类推,不过大小写字母是不同的,原因见下文。
当然可能有人会疑惑了,字母才 26 个,要怎么设定为首的令牌怎么取满 1-31* 中所有节呢?其实这不成问题,因为 for 中的令牌名是以 unicode 编码形式出现的,unicode 编码顺序就是令牌的排序,而几乎所有 unicode 字符均可作为令牌名
在 hanyeguxing 的 《Windows 代码页与字符顺序》:http://bbs.bathome.net/viewthread.php?tid=12329 中声明:
第二类如 set 、dir 、for 等,按 UNICODE 编码顺序排列,不使用 sortkey.nls 顺序。

而 plp626 的 《[讨论]批处理for命令的参数和扩展特性》:http://bbs.bathome.net/viewthread.php?tid=12500 中亦有实例证明:
  1. :: cmd命令行下粘贴如下代码
  2. :: "老" 到 "耣" 的unicode编码(连续地)为 "8001" 到 "8023"
  3. set ss=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  4. for /f "tokens=1-31" %老 in ("%ss%")do @echo %老 %耂 %考 %耄 %者 %耆 %耇 %耈 %耉 %耊 %耋 %而 %耍 %耎 %耏 %耐 %耑 %耒 %耓 %耔 %耕 %耖 %耗 %耘 %耙 %耚 %耛 %耜 %耝 %耞 %耟 %耠 %耡 %耢 %耣
复制代码
而在 0x20~0x7f 范围内(小于 0x7f 都是单字节字符,超过此范围就是由双字节组成的宽字符)究竟有哪些字符可用,我也做过相应测试,证明除了某些字符由于预处理的原因无法使用以外,其余所有字符均可作为令牌名出现。
作者: 过气码农现律师    时间: 2019-1-27 17:37

回复 6# CrLf


    太牛逼了




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2