标题: [文本处理] [已解决]批处理怎样实现文本替换? [打印本页]
作者: 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
- @echo off
- (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
- @echo off
- (for /f "tokens=3,5 delims==> " %%a in (test.txt) do echo %%~a,%%~b,1)>2.txt
- pause>nul
复制代码
一层for就能解决了,为什么还要嵌套呢?
作者: CrLf 时间: 2011-5-21 14:39
3# applba
delims不能用引号作为分隔符
4# Hello123World
这个确实忘了,因为原先是分两步的,简化后忘了统一起来。
作者: CrLf 时间: 2011-5-21 14:44
呀,回帖时忽然有了个猜想,验证下竟然真的可以,看来可以推翻delims不能用"作为分隔符的观点了:- @echo off
- for /f tokens^=1*^ delims^=^" %%a in ("sd"z"vc") do echo %%b
- 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
- @echo off
- (for /f tokens^=2^,4^ delims^=^" %%a in (test.txt) do echo %%a,%%b,1)>2.txt
- 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的特性也可以实现变量延迟哦:- @echo off
- (
- echo %random%
- for /f %%a in ('echo %%random%%') do echo %%a
- pause
- )
复制代码
这是for /f的运行机制决定的
作者: applba 时间: 2011-5-25 06:19
本帖最后由 applba 于 2011-5-25 07:22 编辑
我觉得
引号有转义所有特殊字符(除%)的作用,大多数时候用来转义空格。
for /f后面的一串option,使用引号主要就是为了转义空格和等号,防止预处理时空格和等号作为分隔符分割多个组合的option。
这两个引号在for /f运行的时候会被丢掉,引号中的option在执行时被解释。
既然用双引号是为了转义空格等字符,自然使用^也是可以转义空格和其他特殊字符的。
一般来说只要转义了空格和等号,使用^和双引号效果是一样的。
当然双引号更简单,但是如果涉及到双引号本身做分隔符就必须使用^。
下面是测试,1.txt的内容- abcde^fg^
- abcd"efg"
- abc^de"fg
- abc"de^fg
复制代码
- @echo off
- ::^做分隔符的两种写法
- echo "^做分隔符的写法1"
- for /f "tokens=1-3delims=^" %%i in (1.txt) do echo %%j
- echo "^做分隔符的写法2"
- for /f tokens^=1-3delims^=^^ %%i in (1.txt) do echo %%j
-
- ::"做分隔符的写法
- for /f tokens^=1-3delims^=^" %%i in (1.txt) do echo %%j
- ::下面的写法提示“命令语法不正确 ”
- ::for /f "tokens=1-3 delims="" %%i in (1.txt) do echo %%j
-
- ::"和^一起做分隔符
- 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 编辑
转义字符的确有不少妙用
在某些命令中 几乎所有字符都可以被转义处理- @echo off
- echo 123%%456%%789>1.txt
- echo 123"456"789>>1.txt
- echo 123^&456^&789>>1.txt
-
- for /f tokens^=1-3^,*delims^=^%%^&^"^2 %%i in (1.txt) do @echo ---%%i---%%j---%%k---%%l
- pause
复制代码
回车,手动换行被转义处理- set a=101
- if "!a:~0,1!"=="0" (echo a0===0&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
- else echo a2===1) ^
- else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
- else echo a2===1) ^
- else echo a0===1&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
- else echo a2===1) ^
- else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
- else echo a2===1
-
- rem 规范格式
- set a=110
- if "!a:~0,1!"=="0" (
- echo a0===0
- if "!a:~1,1!"=="0" (
- echo a1===0
- if "!a:~2,1!"=="0" (
- echo a2===0
- ) else (
- echo a2===1
- )
- ) else (
- echo a1===1
- if "!a:~2,1!"=="0" (
- echo a2===0
- ) else (
- echo a2===1
- )
- )
- ) else (
- echo a0===1
- if "!a:~1,1!"=="0" (
- echo a1===0
- if "!a:~2,1!"=="0" (
- echo a2===0
- ) else (
- echo a2===1
- )
- ) else (
- echo a1===1
- if "!a:~2,1!"=="0" (
- echo a2===0
- ) else (
- echo a2===1
- )
- )
- )
-
- 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 中声明改节位置。
比如:- for /f %%a in ("测试 test") do echo %%%%a=%%a %%%%b=%%b
- ::在for 中除了 usebackq 和 skip 外所有开关均有默认参数,上面这句貌似啥也没设置,其实默认为:"eol=; tokens=1 delims=[tab制表符][空格]"
- ::而因为在隐藏的默认参数中,tokens 仅指定了 1,所以只分配第一节内容给了 %%a,而没有分配任何内容给 %%b
-
- for /f "tokens=1,2,4-5 delims=诗《》:" %%a in ("唐诗经典:(插入广告)《长恨歌》白居易") do echo 由 %%a 代诗人 %%d 所著的 %%c 是一部 %%b 。
- ::delims 指定了四个分隔符,tokens 以此为据,指定要取第1、2、4、5 节
- ::这里的 1,2 表示第 1 和 2 节,而 4-5 表示 4 到 5 节(在取连续多节的时候是很有效的简写,此处仅为示例)
- ::而要注意的是,因为此处未在 tokens 中指定第 3 节,故 %%c 跳过第三节,直接与已被声明的第 4 节对应,%%d 则紧随其后,与第 5 节对应。
-
- for /f "tokens=2* delims=-" %%a in ("当前日期-北京时间-2011-11-24") do echo %%b
- ::tokens 中 * 除非是唯一参数,否则必须跟在某个数字后面,以声明其位置。
- ::在 tokens 中指定了某一节后我们可以不引用它,但是他会占用一个对应位置的令牌
-
- for /f "tokens=* delims=0" %%a in ("000001234000") do echo %%a
- ::将第一节与其后内容作为一个整体,去掉前缀的所有分隔符 0
- ::"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 中亦有实例证明:- :: cmd命令行下粘贴如下代码
- :: "老" 到 "耣" 的unicode编码(连续地)为 "8001" 到 "8023"
- 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
- 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 |