【实例】字符串排序之应用

作者:amnesiac 首发:官方论坛中文版

字符串处理是脚本中最常见的一种操作,诚然,在这种操作中正则表达式的强大毋庸置疑,不过大多数人要使用它首先需要进行学习。在实际中,普通的字符串处理命令/函数能解决大量常见的情况,例如 SubStr()Instr() 的功能,在本文中将以具体实例介绍 Sort 一些用法的灵活应用。

来自论坛的问题

为了方便之后分析,这里把整个问题引用过来:

d:\1\文件夹下有一大堆pdf文件, 我现在想用pdftk将它们合并,但是怎么先按页码大小排序呢?
文件名如下, 规律是这样的: 最后一个~符号开始后面就是页码,比如第一个就是166页到210页:(1,2,3,4,5,8,9.pdf 这个则始终应该是排放最开头的,可以想成是0.pdf.)

d:\1\E736B0D95D3C7D0D6D4EA4BF466F22D03yhiahzUahzU7904~166-210.pdf
d:\1\B9DF7166549AC8737AC402DC5F132D5B3yhiahzUahzU7904~1-15.pdf
d:\1\0C73455F2E19ECE5E903095930199CE33yhiahzUahzU7904~1,2,3,4,5,8,9.pdf
d:\1\946349152F37C6BD5561E90C9C6D79463yhiahzUahzU7904~211-227.pdf
d:\1\D3E0FF0E0DA73972F43A8DB89BD540153yhiahzUahzU7904~116-165.pdf
d:\1\AD872772E42DCFA4254B978B5B724B0F3yhiahzUahzU7904~66-115.pdf
d:\1\72EF1017BB29B0302F7E57419E8999D83yhiahzUahzU7904~16-65.pdf

能怎么按页码从小到大排序后放到变量里呢?
比如这样:

A=d:\1\0C73455F2E19ECE5E903095930199CE33yhiahzUahzU7904~1,2,3,4,5,8,9.pdf
B=d:\1\B9DF7166549AC8737AC402DC5F132D5B3yhiahzUahzU7904~1-15.pdf
C=d:\1\72EF1017BB29B0302F7E57419E8999D83yhiahzUahzU7904~16-65.pdf
....

然后我就好调用了:
run d:\PDFtk\bin\pdftk.exe %A% %B% %C% output "d:\1\合并.pdf"

具体分析问题

首先,这肯定属于字符串处理,且为排序问题。字符串排序?自然联想到 Sort 命令

  • 如果您什么想法都没有,这是基本的熟悉程度待提升。很多命令可能一时用不到,但需要基本了解,最基本的可以从查看帮助目录和命令与函数索引开始。

不过粗略观察后可以发现,直接用 Sort 显然不行,需要进行前期处理,例如:
d:\1\72EF1017BB29B0302F7E57419E8999D83yhiahzU~ahzU79~04~16-65.pdf
为了排序,可以先转换成 16-65.pdf,这通过字符串替换完成,实际可以有多种操作方法:

  • 通过 Instr() 找到最后一个 ~(或 ~ahzU79~04~ 的位置,接着 SubStr() 提取(可自由选择类似的命令,这里是我个人习惯);
  • 通过正则表达式利用 RegExReplace() 提取,我想会正则的同学很容易考虑到这点吧,这里不作为首要考虑;

实际中,可以先重命名文件、接着排序新文件名、然后直接构造为 pdftk.exe 的参数(无需又麻烦的赋值给 A、B、C 了)。此外,如果不重命名文件则需考虑用自定义排序(请参照帮助)。
上面是我的思路,下面说说我的具体方法,如果您有兴趣先自己动动手?


我的实现脚本

实现的是否方便往往与对工具的熟悉程度有直接关系(当然对问题的理解也很关键),我个人观点是一般的脚本能用就行,如果没有特殊情况或兴趣却花费大量时间去优化很可能得不偿失。看看具体的脚本:

Str = 
(
d:\1\E736B0D95D3C7D0D6D4EA4BF466F22D03yhiahzU~ahzU79~04~166-210.pdf
d:\1\B9DF7166549AC8737AC402DC5F132D5B3yhiahzU~ahzU79~04~1-15.pdf
d:\1\0C73455F2E19ECE5E903095930199CE33yhiahzU~ahzU79~04~1,2,3,4,5,8,9.pdf
d:\1\946349152F37C6BD5561E90C9C6D79463yhiahzU~ahzU79~04~211-227.pdf
d:\1\D3E0FF0E0DA73972F43A8DB89BD540153yhiahzU~ahzU79~04~116-165.pdf
d:\1\AD872772E42DCFA4254B978B5B724B0F3yhiahzU~ahzU79~04~66-115.pdf
d:\1\72EF1017BB29B0302F7E57419E8999D83yhiahzU~ahzU79~04~16-65.pdf
)
StringReplace, Str, Str, ~, ~~\, All
Sort, Str, N \
StringReplace, Str, Str, ~~\, ~, All
MsgBox, % Str

仔细观察后发现,目标字符串中要比较的那部分子字符串都为数值,且该子字符串前的字符序列比较固定,都为 ~(更长一些则为 ~ahzU79~04~),这样就具备了使用 Sort 中 \ 的条件,因此代码出来了:

Sort, Str, N \

在比较之前先替换就行了,不再赘述。有趣的是,当我在 Vim 中写出上面的代码时,我又发现一个更简便的方法:

Sort, Str, N P57

从第 57 个字符开始比较,显然这种方法得益于观察,因为我 Vim 中用等宽字型,一眼就能看出待比较子字符串的起始位置相同(在上面代码块中也能看出来,但最初在论坛看到问题时我没发现)。显然,这里打破了我之前无法直接使用 Sort 的想法。

  • 尽管这里 d:\1\0C73455F2E19ECE5E903095930199CE33yhiahzU~ahzU79~04~1,2,3,4,5,8,9.pdf 会排在第二位,但这是次要问题。

最后,问题到这里并非终结,运用之妙存乎一心,如果您有好例子或好问题,欢迎交流。为了分享我常常去构造应用场景,效果往往不理想,让我想到教科书式的苍白无力,而实际中的使用则是那么的生动活泼。

必要的补充

前面没有说完美的解决,真不仅只是小心,现在问题来了。849112292 在问题评论中指出:

\ 和 N 选项不能同时起效

我太大意了,一段时间不用很多要点就忘了,以前翻译帮助时这些印象都非常深刻的。您发现了吗?如果没有,那么您动手了吗?
思路还是简单,直接按位置排序,要数值比较则需先重命名,自定义排序仍然行的通。继续发现问题吧,不过思路我只能分析到这里了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 个人学习批处理的初衷来源于实际工作;在某个迭代版本有个BS(安卓手游模拟器)大需求,从而在测试过程中就重复涉及到...
    Luckykailiu阅读 4,702评论 0 11
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 99,215评论 9 467
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • 《火车》 住的地方 离火车站不远 常常去车站后面 伴着泛橙的夕阳 铁轨和电线的线条 指向远方 那画面 真的很美 常...
    我叫王村村阅读 4,876评论 38 130