[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[原创] 批处理命令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指出了第②点中的错误;
1

评分人数

尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

学习了!
谢谢精心的讲解。支持!!!

TOP

这么好的文章先收下了!多谢

TOP

好详细,分析得如此透彻~~~

TOP

  支持楼主!斗胆补充一点:
  偏移量是一个序数,在计算机语言中,序数是从第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 编辑 ]
2

评分人数

TOP

  楼上的补充非常及时,让大家对偏移量的理解又更进了一步。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

哈哈,终于弄懂了一个小白疑问:“set var=%str:~偏移量,长度%”中的两个%号是一对的。总算看懂这格式了^_^

TOP

学问多多啊。多谢分享

TOP

我知道回复“谢谢”两个字是多么的俗不可奈,但除了说声“谢谢!”我又能拿什么来表达的心情?

TOP

原帖由 namejm 于 2008-5-3 16:43 发表
  提取倒数第2个及其之前的3个字符:set var=%str:~-6,4%


这句不太明白,好像应该是set var=%str:~-5,4% 吧???
1

评分人数

    • batman: 敢于怀疑,好!!!PB + 5

TOP

  呵呵,谢谢指正,是我错了,已经在顶楼更正。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

那如果我要截取1、3、5这三个数字的话(即跳着截取),该如何通过代码实现呢?

TOP

我写的……

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 个,剩下的是最后两个”

我个人是在写特效的时候经常会很充分利用这些性质。

TOP

又上了一课
看后受益者留名~~~

TOP

原来就和数组计数一样,[0]     [1]     [2]   共3个元素                           
                                              |        |         |
                                           1st      2nd    3rd

TOP

返回列表