标题: [原创] 批处理命令set截取字符详解 [打印本页]
作者: namejm 时间: 2008-5-3 16:43 标题: 批处理命令set截取字符详解
在批处理中,set的功能有点繁杂:设置变量、显示环境变量的名及值、做算术运算、等待用户的输入、字符串截取、替换字符串,是我们常用的命令之一。
在字符串截取方面,新手因为没能注意到偏移量的问题,很容易提取到错误的字符串,因此,特开此帖,详细解释 set 截取字符的用法。
我们先来看一个例子:
set str=123456789
现在,我需要提取变量 str 中的第一个字符,那么,该怎么写命令呢?
set var=%str:~1,1%?我想,这很可能是很多粗懂set用法的新手们的第一反应,实际上,这条语句提取到的是字符"2",并不是我们想要的"1",也就是说,set var=%str:~1,1% 提取到的是字符串第二位上的字符,而不是第一位上的,这是什么原因呢?
原来,set 命令从左到右做字符截取的时候,是以整个字符串的第一个字符为起点来计算要截取字符的偏移量的,也就是说,截取字符的时候,set 会计算提取后字符串的第一个字符相对于整个字符串第一个字符偏移了多少字符的长度。请注意,set 是按偏移量而不是字符的绝对位置来提取字符的,这一点非常重要。只要牢记这一点,大家在截取字符的时候,将会不再在这个问题上犯错。
现在,我们可以把截取字符的命令用一条语句模式来表示,那就是:set var=%str:~偏移量,长度%。
我们来详细解读这条语句模式的含义:
首先,我们需要把要操作的字符串赋予一个变量,在这条语句中,是把字符串赋予了变量 str ;然后,我们需要确定一下我们想提取的字符串是哪一部分,比如说要提取字符串第2个字符及其之后的3个字符,或是提取字符串第5个字符及其之后的4个字符……,最后,计算偏移量及长度,比如要提取字符串第2个字符及其之后的3个字符,那么,也就是提取相对于第一个字符偏移量为1、提取后的字符串长度为4的字符串,写成语句就是:set var=%str:~1,4%。
到目前为止,我们只谈到了很简单的截取操作,如果碰到比较复杂的提取需求,比如:提取第2个字符及其之后的所有字符、提取最后的3个字符、提取倒数第2个及其之前的3个字符、提取除了最后4个字符的字符串……那又该怎么办呢?别着急,set 命令在设计的时候就已经充分考虑到我们的复杂需求,只要对刚才我们提到的字符截取语句稍做改动,就可以很轻松地完成任务。
我们知道,数字的正负可以用+-符号来表示,同样的,方向的正反也可以用+-来标注。在 set 做字符截取的时候,引入了+-符号来表示字符截取的方向:从左到右截取为+,从右到左截取为-,所以,set var=%str:~1,4% 也可以写成 set var=%str:~+1,+4% ,只是在从右到左截取的时候,情况发生了一点变化,那就是:偏移量的起点以整个字符串最后一个字符的后一位来计算。现在,我们可以来回答上一段中提出的一些问题:
提取最后的3个字符:set var=%str:~-3%
提取倒数第2个及其之前的3个字符:set var=%str:~-5,4%
提取除了最后4个字符的字符串:set var=%str:~0,-4%
看了上面三种需求的代码,大家可能又会产生新的疑问:第一条怎么只有一个数字啊?第三条最后一个数字是负号,又表示什么意思呢?
原来,在 set var=%str:~偏移量,长度% 这样的语句中,如果没有逗号及其之后的长度,就表示截取偏移量位置上及其之后的所有字符,如果长度的值为负数,则表示抛弃最后几个字符。
现在,我们可以对任意位置上的字符做提取工作了(假设 set str=123456789):
① 提取1: set var=%str:~0,1% 或 set var=%str:~0,-8% 或 set var=%str:~-9,1%
② 提取2: set var=%str:~1,1% 或 set var=%str:~1,-7% 或 set var=%str:~-8,1%
③ 提取9: set var=%str:~8,1% 或 set var=%str:~8% 或 set var=%str:~-1,1% 或 set var=%str:~-1%
④ 提取123:set var=%str:~0,3% 或 set var=%str:~0,-6% 或 set var=%str:~-9,3%
⑤ 提取234:set var=%str:~1,3% 或 set var=%str:~1,-5% 或 set var=%str:~-8,3%
⑥ 提取789:set var=%str:~6,3% 或 set var=%str:~6% 或 set var=%str:~-3,3% 或 set var=%str:~-3%
最后,我们来总结一下字符截取的规律:
1、截取字符串可以用 set var=%str:~数值1,数值2% 这样的语句来实现;
2、字符的截取是以偏移量来计算的,而不是以字符的绝对位置来计算;
3、当数值1为正数时,表示从左到右截取;当数值1为负数时,表示从右到左截取;
4、当数值2为正数时,表示要截取后字符串的长度;当为负数时,表示要抛弃的最后几个字符长度;
5、当数值2及其之前的逗号不存在时,表示截取的是第(数值1+1)个字符及其之后的所有字符;
——————————————————
感谢halili 指出了第⑤点中的错误;
感谢woxingwoshu007指出了第②点中的错误;
作者: lingfeng 时间: 2008-5-3 20:17
学习了!
谢谢精心的讲解。支持!!!
作者: binaryman 时间: 2008-6-4 17:43
这么好的文章先收下了!多谢
作者: tangfu 时间: 2008-6-14 09:58
好详细,分析得如此透彻~~~
作者: shqf 时间: 2008-8-2 21:53
支持楼主!斗胆补充一点:
偏移量是一个序数,在计算机语言中,序数是从第0个开始的, 所以计算机中的第0个就是通俗语言中的第1个,而计算机中的第1个是通俗语言中的第2个......这样就很容易理解SET是如何提取字符了。如上例中,%str:~0,1%,表示第0个字符开始(通俗讲的第1个字符),取1个,也就是第一个字符为1, %str:~6,3%,表示从第6个字符开始(通俗讲的第7个字符),取3个,也就是第七到第九个字符为789。
[ 本帖最后由 shqf 于 2008-8-2 21:58 编辑 ]
作者: namejm 时间: 2008-8-2 23:09
楼上的补充非常及时,让大家对偏移量的理解又更进了一步。
作者: sagaman6095 时间: 2008-8-3 11:15
哈哈,终于弄懂了一个小白疑问:“set var=%str:~偏移量,长度%”中的两个%号是一对的。总算看懂这格式了^_^
作者: 愚无尽 时间: 2008-8-3 19:33
学问多多啊。多谢分享
作者: tjtchly 时间: 2008-8-8 01:00
我知道回复“谢谢”两个字是多么的俗不可奈,但除了说声“谢谢!”我又能拿什么来表达的心情?
作者: zyc411277063 时间: 2008-11-2 23:20
原帖由 namejm 于 2008-5-3 16:43 发表
提取倒数第2个及其之前的3个字符:set var=%str:~-6,4%
这句不太明白,好像应该是set var=%str:~-5,4% 吧???
作者: namejm 时间: 2008-11-3 01:01
呵呵,谢谢指正,是我错了,已经在顶楼更正。
作者: akiraakito 时间: 2008-11-14 15:48
那如果我要截取1、3、5这三个数字的话(即跳着截取),该如何通过代码实现呢?
作者: 523066680 时间: 2008-11-15 16:43 标题: 我写的……
help的解释,我是很难理解了(现在还勉强理解) 所以后来采用了另一种方式理解:
~代表省略, 后面的那个数字代表省略后,剩下的字符串被保留的个数。若为负则需计算。
不管是省略还是保留,指的都是前面的。
---------规律-----------%a:~n,m% 省略前n个,保留剩下的前m个
---------规律-----------%a:~-n,-m% 省略前 总数-n 个,保留剩下的前 总数-m 个
例子:set a=123456789 共9个字符
echo,%a:~0,5% (前面不省略)保留前 5个
echo,%a:~0,-5% (前面不省略)保留前 9-5=4个 (而不是后5个。)
echo,%a:~5% 省略前5个,剩下的保留
echo,%a:~-5% 省略前9-5=4个,剩下的保留
echo,%a:~-3,-2% 省略前9-3=6个(剩3个:789),剩下的再保留前3-2=1个
结果显示7
_____________________________________________________________________
(我个人)了解这里的规律部分以后,写批处理的时候是不用想太多的,很快就知道要如何配置
而用help的解释,我总是要理解很久。
举一些例子吧,echo,%time:~-2% 可以显示时间的最后两位,很方便吧,一想就知道
“省去前面的 总数-2 个,剩下的是最后两个”
我个人是在写特效的时候经常会很充分利用这些性质。
作者: MarkovChain 时间: 2008-12-1 00:13
又上了一课
看后受益者留名~~~
作者: MarkovChain 时间: 2008-12-1 00:19
原来就和数组计数一样,[0] [1] [2] 共3个元素
| | |
1st 2nd 3rd
作者: pengpangxiong 时间: 2009-1-3 15:00 标题: 一个字.好
老师说过帮了你的人,要对他说谢谢.我是听话的孩子哦.
作者: Batcher 时间: 2009-1-3 19:45 标题: 回复 12楼 的帖子
建议把顶楼的教程多看几遍,自己多写代码练习一下。- @echo off
- set str=123456789
- set var1=%str:~0,1%
- set var3=%str:~2,1%
- set var5=%str:~4,1%
复制代码
作者: 5810239q 时间: 2009-3-25 16:54
又学到东西了
作者: halili 时间: 2009-4-6 11:25
⑤ 提取234:set var=%str:~1,3% 或 set var=%str:~1,-6% 或 set var=%str:~-8,3%
?????结果好像是只能得到23吧 我是新手 请老鸟们多多指教啊
作者: namejm 时间: 2009-4-6 13:43
感谢你指出我的错误,正确的代码应该是 set var=%str:~1,-5%,我写教程的时候多抛弃了一位了,已经改正,谢谢。
作者: energy2009 时间: 2009-4-6 22:44
set str=1 2 3 4 5 .....98 99 100
怎么样得到奇数项??
作者: mahuifang 时间: 2009-4-7 17:10 标题: 原创:set截取字符--新的简易解释
看过尘土飞扬的《set截取字符详解》、youxi01的《变量字符截取 点点通》,终于明白了Set如何截取字符的,感谢他们!
但是,我想出了更容易理解的解释,本着百花齐放、勇于探新的精神,呵呵,虽说是菜鸟,也不妨讲出来,使更多菜鸟能够快速地理解和掌握。言归正传,开始了。
set var=1234567890
echo %var:~4,-2%
结果是 var=5678
上例中,截取字符,是按位操作的,下面就以比较复杂的“截取中间字符串”为例,说明一下怎样快速理解并掌握字符的截取方法。
先看下面的新解释:
~:删除前几位;(删前)
~-:保留后几位;(保后)
如果一次操作的结果,无法到达目的,需要在第一次操作的结果上,再进行二次操作:
,:保留前几位;(保前)
,-:删除后几位;(删后)
例如:set var=1234567890
%var:~4% ~4删除前4位,即var=567890;
%var:~-6% ~-6保留后6位,即var=567890;
%var:~4,-2% ~4删除前4位,即var=567890,再由“,-2”删除后2位,即var=5678;
%var:~-6,4% ~-6保留后6位,即var=567890,再由“,4”保留前4位,即var=5678;
%var:~4,4% ~4删除前4位,即var=567890,再由“,4”保留前4位,即var=5678;
%var:~-6,-2% ~-6保留后6位,即var=567890,再由“,-2”删除后2位,即var=5678;
通过仔细研究这6个例子,你可以很容易的理解set截取字符的方法,加以简单练习,就可以很快的掌握了。
作者: wcmcool 时间: 2009-4-8 09:07
非常感谢楼主的讲解,真是受益匪浅啊
作者: qjfke 时间: 2009-4-16 16:19
看了一下,谢谢了,,
作者: woxingwoshu007 时间: 2009-4-20 17:31 标题: 回复 1楼 的帖子
十分感谢楼主提供这么好的学习帖子.............我阅读完发现小错误一处.不知道是楼主故意给我们新手思考的还是笔误.
② 提取2: set var=%str:~1,1% 或 set var=%str:~1,-8% 或 set var=%str:~-8,1%
中的set var=%str:~1,-8%应该是
set var=%str:~1,-7%吧...楼主看看
作者: zhushjbathhome 时间: 2009-4-27 19:27
看了楼上的讲解,结合自己的理解,把截取字符归纳为4条:
1、set var=%str: ~n, m% 从n+1 开始,从左至右连续m个
2、set var=%str: ~n, -m% 从n+1 开始,去掉最后m个
3、set var=%str: ~-n, m% 截取最后n个,从左至右连续m个
4、set var=%str: ~-n, -m% 截取最后n个,去掉最后m个
作者: kanfengjing 时间: 2009-4-29 09:46
好东西学习再学习
作者: xiaotian 时间: 2009-5-5 11:11
讲得真是太祥细了,谢谢
作者: xmaoh234 时间: 2009-5-8 13:20
哦,明白了
(1),偏移量前的+,-,表示方向,,向左或右,
长度前的+,-,+表示保留,-表示去掉,
set var=1,2,3,4,5,6,7,8,9
(2)如果偏移量前是+,那么它的第一个元素的下标序列号为0....(下标序列号最大是8)
而 如果偏移量前是-,那么也就是从右向左开始,它的倒数第一个是-9,而不是-8.
强!!!!
[ 本帖最后由 xmaoh234 于 2009-5-8 13:31 编辑 ]
作者: liuks001 时间: 2009-7-25 20:17
学习了,感谢LZ的详细讲解让新手也能看懂!
作者: nopr 时间: 2009-8-3 12:27
非常感谢楼主,现在也明白了.
%var:~m,n% 省略M个,保留N个
%var:~-m,-n% 保留最后m个,抛弃最后n个
作者: gigiqb 时间: 2009-8-3 16:31
学到新东西了感谢lz,我会好好学滴
作者: lazygc520 时间: 2009-8-18 09:35
我觉得楼主应该写清楚,字符串是以“\0”结尾的!所以取逆的时候是从"\0"取起的。
[ 本帖最后由 lazygc520 于 2009-8-18 09:38 编辑 ]
作者: 5566ljlj 时间: 2009-10-27 14:38
先来学习学习了!!!
作者: huxu823 时间: 2009-10-28 16:42
谢谢分享,学习了!!
作者: craig_we 时间: 2009-11-27 17:25
测试一下:
set str=12345
echo %str:~1,2%
输出12
学会了,谢谢
作者: a522911404 时间: 2009-12-3 12:42
支持!!!!!!!!!!!!
作者: kevinm 时间: 2009-12-5 13:21
收藏了 非常有用 多谢了
作者: wgoxm521 时间: 2010-1-17 18:09 标题: 好
哈哈。写的太详细了,累着你了吧。
作者: gxuan2008 时间: 2010-1-26 14:52
看着有点晕,我是这么理解的。
set var=%str:~数值1,数值2%
数值1:正前舍,负后取;
数值2:正前取,负后舍;(数值2的规则是在数值1取数完成后)
这样是好记点,但不知道对不对。
[ 本帖最后由 gxuan2008 于 2010-1-26 14:54 编辑 ]
作者: johnsci 时间: 2010-1-26 15:24
学问多多啊。多谢分享
作者: reddragon1314 时间: 2010-4-3 20:44
这篇教程确实不错。学习了。
作者: paladinjin 时间: 2010-8-25 16:26 标题: 回复 13楼 的帖子
看来还是要总结规律啊 呵呵
作者: zixuan 时间: 2011-1-25 22:25
讲的很详细,学习了。。。
作者: Hello123World 时间: 2011-1-26 14:19 标题: 本来也想发个教程的,原来早就发了
(另一种理解set命令截取字符的方法)
假设有以下这么个批处理:- @echo off
- set h=heblo
- echo %h:~数值1,数值2%
- pause
复制代码
当数值1为正数2时,意为截掉左边前2个字符并保留剩下的,当数值1为负数-2时,意为截取右边2个字符到“保留剩下的”。
当数值2为正数2时,意为截取“保留剩下的”左边2个字符,当数值2为负数-2时,意为截掉“保留剩下的”右边2个字符。
来句口诀:
正左负右。
数值1,正左截掉,负右截取。
数值2,正左截取,负右截掉。
理解偏移的口诀:
还是针对前面的代码,首先想象在 heblo前有个小数点,即 .heblo
正左到右,负右到左。
数值1,始终截取右边部分。
数值2,始终截取左边部分。
[ 本帖最后由 Hello123World 于 2011-1-27 10:48 编辑 ]
作者: dosbat 时间: 2011-4-17 13:26
本帖最后由 dosbat 于 2011-4-17 13:28 编辑
set str=123456789
set var=%str:~数值i,数值j%
~数值i:当i>=0时,表示跳过前面的i个字符;
当i<0时,表示跳过前面(n-i)个字符,其中n为字符串长度,换言之,即保留最后i个字符
例如:当我想截取str的第4个字符开始的3个字符时,要跳过前面3个字符,故数值i=3,又因为长度为3,故数值j=3,写成批处理语句为:set var=%str:~3,3% 也可以写成 set var=%str:~-6,3%
不知道我说清楚没有 欢迎批评指正
作者: liaobin 时间: 2011-4-20 07:15
好顶必回。。。。
作者: asd821089612 时间: 2011-7-21 07:56
多谢,我学到了很多东西
作者: 秋风·飞扬 时间: 2012-5-12 18:13
本帖最后由 秋风·飞扬 于 2012-5-12 18:22 编辑
总结,① 当只有一个参数存在的时候,系统会默认当它为偏移量。 (set str=%str:~nn%)
此时,若nn为正,那么就偏移nn个取后面的。
此时,若nn为负,那么就从后面往前偏移nn个位置,开始往后取(也就是说后面nn个全部被取到了)。
② 0就是空,空就是0。 (set s=%str:~mm,%)
③ 长度为零就不取了呗。 (set s=%str:~mm,%)
④ 偏移量为正的时候 (set s=%str:~mm,nn%)
如果nn为正,那么就偏移mm个位置后,取后面nn个字符。
如果nn为负,那么就偏移mm个位置后,在从后面去掉nn个字符,取中间的。
⑤ 偏移量为零的时候 (set s=%str:~0,nn%)
如果nn为正,那么就不偏移,直接去nn个。
如果nn为负,那么就不偏移,从头取,但除了后nn个。
⑥ 偏移量为负的时候 (set s=%str:~-mm,nn%)
如果nn为正,那么就从尾巴开始往前偏移mm个位置后,开始回头取字符,个数为nn个。
如果nn为负,那么就从尾巴开始往前偏移mm个位置后,开始回头取字符,但是要排除掉后面的nn个字符。
作者: cjiabing 时间: 2012-5-15 00:30
本帖最后由 cjiabing 于 2012-5-15 00:39 编辑
格式:%str:~m,n%
str表示字符串变量,是一个从左至右的单向坐标轴,用位数表示单位,用横杠“-”表示反方向。
m表示指定位数、定位,从字符串的哪个位数开始提取;负的表示从后面第几位开始提取。
n表示指定个数,提取多少个字符;负的表示去掉后面多少个字符。
举例:
set str=我爱北京天安门
“我爱北京天安门”一共是7个字符;
字符 顺序 偏移量
-------------------------
我 1 0
爱 2 1
北 3 2
京 4 3
天 5 4
安 6 5
门 7 6
顺数的时候偏移量向后一位,也就是将位数减去1得到偏移量。比如第三位是“北”,偏移量就是3-1=2,提取时写成%str:~2,1%。
1、echo %str:~0,7%
表示从第1位开始提取,7表示提取7个字符串,显示“我爱北京天安门”。
2、echo %str:~0,3%
表示从第1位开始提取,一共提取3个,结果是“我爱北”。
3、echo %str:~4,3%
表示从第5位开始提取,一共提取三位,结果“天安门”。
4、echo %str:~0,-3%
表示从1位开始提取,排除掉、去掉最后3位,结果是“我爱北京”。
5、echo %str:~-3,3%
表示从倒数第3位开始提取,一共提取3位,结果是“天安门”。
6、echo %str:~-5,-2%
表示从倒数第5位开始提取,排除最后两位,提取两者中间的字符,结果是“北京天”。
从后面往前面数第5位是“北”,最后两位是“安门”,中间的就是“北京天”。
实在无聊在此乱打,随便看罢!如果要口诀可以这样:
左位右数——表示左边m是定位,右边n是定数;
左位负倒——表示左位是负“-”时从后面数起;
右数负除——表示右位是负“-”时除掉后面的位数。
因此:
正时:左定位数,右定个数
负时:左边从后数起,右边去掉后位
作者: baisebaoma 时间: 2012-5-23 17:31
好帖必顶不解释!楼主辛苦了,学到了很多——刚好用上了。
作者: stance 时间: 2012-11-28 16:16
本帖最后由 stance 于 2012-11-28 17:09 编辑
感谢好贴!建议改进机器语言到自然语言的转换:
提取最后的3个字符:set var=%str:~-3%(提取从后往前数,自倒数第3个字符开始往后的连续字符:set var=%str:~-3%)
提取倒数第2个及其之前的3个字符:set var=%str:~-5,4%(提取从后往前数,自倒数第5个字符开始往后的4个连续字符:set var=%str:~-5,4%)
提取除了最后4个字符的字符串:set var=%str:~0,-4%(提取从前往后数,自第0个至倒数第4个字符之间的连续字符:set var=%str:~0,-4%)
莫怪吹毛求疵,只是希望便于理解。
作者: tanjiunnya 时间: 2012-12-15 14:49
感谢,这个很值得学习的!
作者: bclcc 时间: 2013-4-26 16:39
字符截取的一般形式:set var=%str:~数值x,数值y%,总共4种情况:x>=0,y>=0;x>=0,y<0从;x<0,y>=0;x<0,y<0;还有一种情况只存在一个数值,较简单。
作者: wangx 时间: 2013-9-16 14:28
每天进步一点,谢谢分享。
作者: suseek 时间: 2013-9-16 15:54
取偶数位,是否正确?
ECHO OFF
set var=1234567890
for /a %%i in (1,2,9) do (echo %var:~%%i,1%)
pause
作者: suseek 时间: 2013-9-16 15:56
36楼输出的是23
作者: DAIC 时间: 2013-9-16 16:16
回复 58# suseek
不正确,你亲自测试一下就知道了。
作者: suseek 时间: 2013-9-16 16:34
谢谢指正
ECHO OFF
setlocal enabledelayedexpansion
set var=1234567890
for /l %%i in (1,2,9) do (
echo !var:~%%i,1!
)
)
pause
作者: changedirectory 时间: 2013-10-5 09:00
多谢!!!感谢大神!
作者: James_vivi 时间: 2013-10-20 23:23
收下了这set 命令
作者: wabata118 时间: 2013-10-24 17:32
不错哦,学习了
作者: citear 时间: 2014-5-13 14:16
请允许我补充一丢丢:
对于数值1和数值2 的取值范围关系
当两者为负数的时候 数值1要小于数值2 否者为无效吧
作者: ezaohaha 时间: 2014-10-20 21:53
你的教程总是这么朴实 易懂 可惜你的一日一教学成了断章 后续的虎头蛇尾
作者: shelluserwlb 时间: 2014-11-10 15:19
本帖最后由 shelluserwlb 于 2014-11-10 16:22 编辑
%VAR:~数值1,数值2%
1. 数值1无论正负都表示开始截取起始位置。
2. 数值2若为正数表示截取个数,若此值超过剩余字符数,则会截取剩余的全部字符。
数值2若为负数表示截取结束位置。
3. 若缺少数值2和其前面的逗号,则表示截取从数值1所指的位置开始到最后一个字符为止。
4. 正数:从左到右数(从0开始算) 负数:从右到左数(从0开始算但不能为0)。
作者: 750795191 时间: 2016-3-23 11:19
回复 36# craig_we
那个输出是23吧??
作者: allyn 时间: 2022-7-9 19:07
感谢 学到了
作者: yyz219 时间: 2022-7-22 13:30
我不是怎么看得明白
作者: ANSL 时间: 2022-11-4 20:43
谢谢楼主,学习了!
作者: pda8888 时间: 2023-1-23 19:21
本帖最后由 pda8888 于 2023-1-23 19:22 编辑
虽然我是新人一枚,也斗胆发表一下见解:
%var~:n,m%,
其中,n是指起始位置,m是指取多少个字符。
1、如果n是正数,则从左边开始数,起始位置是0,如果n是负数,则从字符尾部开始数。
2、如果m是正数,是从左往右计数,如果m是负数,是从右往左计数。
这样更易理解和记忆,不知说对了没有。
反正就是定义起始位置和取多少个字符,不涉及到保留和舍弃的复杂理解和记忆。
作者: zxlagyyy 时间: 2023-6-30 08:01
不能完全看懂。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |