各位看官,由此问题延伸出来的Shell脚本讨论,有相同正则及shell实现问题可看如下回复 rename CLI 解决楼主问题方案请看 9楼回复的帖子
#rename CLI Mac可通过brew安装
rename -v 's/.*(\d{17}[\dxX]).*\.(.*?)/$1.$2/' * -n
正则表达式验证网址:https://regex101.com/
以下内容涉及到由各行业大佬对于shell脚本的讨论 关键词:正则、rename、elvish、zsh、shell 、脚本语言、shell传参、bash
elvish shell官网:https://elv.sh/
elvish Quick look:https://itsfoss.com/elvish-shell/
ohmyzsh官网:https://ohmyz.sh/
延伸讨论: https://www.v2ex.com/t/877843 不限 shell 类型的情况下,用 shell 脚本可以实现哪些骚操作?
1
RayGZJ OP 有 rename 的 CLI 工具 但是 man rename 是在太干 也考虑 python 实现或许更简单些?
|
2
yfugibr 2022-09-04 23:08:06 +08:00
```
rename -v 's/.*(\d+).*\.(.*?)/$1.$2/' * -n ``` 确定没问题就去掉 -n 参数 |
3
yfugibr 2022-09-04 23:10:06 +08:00 1
|
6
Jirajine 2022-09-04 23:14:51 +08:00 4
用 elvish ,比 bash 顺手,也比 Python 方便:
put **.jpg | peach {|name| use re var number = (re:replace '[^0-9]' '' $name) mv $name $number.jpg } peach 并发执行,换成 each 顺序执行。 |
7
Jirajine 2022-09-04 23:17:08 +08:00
带 X 换成 '[^0-9X]'
|
9
yfugibr 2022-09-04 23:22:14 +08:00
|
10
RayGZJ OP |
11
yfugibr 2022-09-04 23:29:37 +08:00
|
12
wxf666 2022-09-04 23:33:06 +08:00
这样?
rename -n -v 's/^\s*.*?\s*(\d+[\dxX])\s*.*?(\.[^.]+)$/$1$2/' * 一样,确定没问题就去掉 -n 参数 |
13
wxf666 2022-09-04 23:35:43 +08:00
也对,名字里没有 0-9 x X ,直接 's/^.*?(\d+[\dxX]).*?(\.[^.]+)$/$1$2/' 就好
|
14
wxf666 2022-09-04 23:39:18 +08:00
|
15
Jirajine 2022-09-04 23:54:41 +08:00
|
17
wxf666 2022-09-05 00:15:01 +08:00 1
@Jirajine 另外,你那个示例的逻辑,可以写成:rename 's/[^\dxX]//g; s/$/.jpg/' *
我觉得,交互式下的 shell ,简短快捷,还是很重要的吧 word splitting 、特殊语法 也是为这个目的服务的 不搞这些,就不可避免地会写长 简短 和 美观,感觉不可兼得,就看个人喜好了 反正交互式下,我是愿意阅读 bash 规则,牺牲一定可读性,来换取输入时的便捷的 就好比有人会放弃易读的拼音,练习五笔,去换取快捷打字一样(我折中一下,学了个双拼。。) |
18
aloxaf 2022-09-05 00:57:11 +08:00
来用 zsh
autoload -Uz zmv zmv -n '*.jpg' '${f//[^0-9X]/}.jpg' |
19
haoliang 2022-09-05 01:44:44 +08:00
正巧我打算换个 shell ,看到楼上对 elvish 、bash 、zsh 的示例,我决定试试 elvish ,哈哈。
虽然我的 login shell 是 zsh ,但我从来都只写 bash 脚本,复杂的就换 python 了。可以说 zsh 是我最熟悉的陌生人,它的大部分功能我都没用过。elvish 用 go 实现,方便阅读实现、定制,相见恨晚啊! |
20
Jirajine 2022-09-05 02:37:33 +08:00
@wxf666 你上面的那种长正则,可读性很差的,不常写正则的人不用 regex101.com 这样的工具都看不懂。
rename 自己又发明了一种 dsl 语言,不熟悉的人用起来有额外的心智负担。而且你还得同时处理 shell/rename 自己的语言 /regex 的转义,再配上 glob 。 word splitting 可不是简短,是历史包袱,导致所有变量引用都得用引号括起来。 特殊语法如 man zshexpn 看一看,正常编程语言简单的字符串处理有多麻烦。 elvish 也是为交互式设计的,完全符合简短快捷易输入,PowerShell 才是故意搞得冗长、难以输入并美其名曰“可读性”的。 |
21
Jirajine 2022-09-05 02:43:33 +08:00
@wxf666 那个示例这样写便于阅读和复制粘贴,交互式输入把变量 inline 一下也只有一行。use re 是导入包,相当于 import 。
|
22
mrfox 2022-09-05 03:35:28 +08:00
前不久听过 elvish ,去官网看了下,网上也搜索了下没找到什么教程
挺难上手的还是 |
23
wxf666 2022-09-05 10:38:33 +08:00
@Jirajine
> 用 elvish ,……,也比 Python 方便 直接和 Python 比不公平吧。。 后者定位是脚本语言,你前者拿来当交互式 shell 用的。。 Python 也有个 shell 实现,xonsh ,你试过吗?感觉咋样? > 长正则,可读性差,有人看不懂 看各人咯,不想写正则,多半也是自己写代码,模拟实现了正则的逻辑出来 可能写的多了后,厌烦了,也会转正则那边去了 > rename 自己又有一种 dsl 语言 你是说很多命令有自己风格的正则嘛? 确实是个问题。但好像也就几种风格:posix bre ere 、pcre \d 不支持就试试 [0-9] 或 [[:digit:]] 呗。反正支持的正则特性都差不多 > shell rename 转义,glob shell 里用 'pattern' 来表达 rename 的正则,也没啥麻烦吧 glob ?*.jpg ?有啥问题么。。 > word splitting 可不是简短,是历史包袱 我觉得 bash 为实现下列功能,整体花费的代价很小。elvish 是如何实现的? 1. 变量 /subshell 捕获,被 split 成多个参数( bash:$s ,$(xxx)) 2. 被作为一个参数传递( bash:"str: $s","captured: $(xxx)") > man zshexpn 看一看特殊语法,字符串处理有多麻烦 我只用过 bash ,没用过 zsh 。bash 支持的字符串处理确实不多 > PowerShell 才是故意搞得冗长、难以输入并美其名曰“可读性”的 反正那人坚持说 powershell 因为冗长而强大。bash 简短易出错,容易友尽、吃牢饭等。。 另一个人说 shell 命令简短,容易记混 ln ls ll du dd df …… |
24
laqow 2022-09-05 10:40:58 +08:00
把所有文件名 ls 出来,在文本文件中用懂的语言正则完确定没错了,再逐行 rename ori new
|
25
webcape233 2022-09-05 10:42:34 +08:00 via iPhone
搞这么复杂,直接 grep 出来数字不接行了
name=张三 12345 new_name=$(echo $name |grep -oE "[0-9]+") mv $name $new_name |
26
webcape233 2022-09-05 10:45:04 +08:00 via iPhone
有 x 正则再加一个 改成"[0-9]+[xX]"
|
27
webcape233 2022-09-05 10:46:48 +08:00 via iPhone
疏忽了扩展名,可以把扩展名提取出来 ,后面再加上
|
28
aloxaf 2022-09-05 10:51:18 +08:00
|
29
Jirajine 2022-09-05 11:24:44 +08:00
@wxf666 这里说的是脚本,因为 Python 不是 shell ,调用命令即使使用 sh 这样库也不如 shell 直接。xonsh 就是个玩具,oil/osh 倒是一个类 Python 的 shell ,但 UI 比 elvish 差太多,而且是用一套自制工具链写的。
像你那个 rename ,用$1 $2 来引用 capture group 就是个自己的语言,这玩意不是 shell 变量,elvish 及其他高级编程语言都不需要多此一举,一致性更好。 用 shell 构建另一个语言的字符串,你得考虑 shell 的转义(单引号或$符号)、dsl 的转义( /符号)、正则特殊字符的转义,glob 又是一套类似正则,但又不同的匹配语言,太多不一致性和心智负担了。 word splitting 是因为 POSIX sh 一切皆 string ,缺乏 list 类型,导致 IFS 的 trick 和引用变量总是需要 quoting 。用 shell 处理包含空格的字符串简直是 nightmare 。 elvish 是支持结构化数据类型的,string 永远是 string ,不会被自动 split 也不需要 quoting 。你要传多个参数,直接用 list 就行了,subshell ( elvish 里是 output capture )可以像 golang 一样多返回值,只要输出多个值自然就是多个参数。 var a b = (put 1; put 2) echo $a $b c 等价于 echo (put 1; put 2) c bash 和 zsh 一样,也有一大堆晦涩的 expansion 语法,难记难写,不过 zsh 是最“强大”的,支持的功能最多,从 sh 到 bash 到 csh 再到 zsh 原创的,也是最混乱的。 elvish 也是崇尚简短的,你看内置函数的命名,一个单词或一个单词加一个介词,命名风格也没有需要 Shift 才能输入的符号,如 to-json 对比 PowerShell 里 ConvertTo-Json 。 |
32
aloxaf 2022-09-05 11:35:43 +08:00
@Jirajine #29
> 像你那个 rename ,用$1 $2 来引用 capture group 就是个自己的语言,这玩意不是 shell 变量,elvish 及其他高级编程语言都不需要多此一举,一致性更好。 这话就有点罔顾事实了啊,用 $1 、$2 来引用 capture group 明明是通用做法,elvish 自己都是这么用的: https://elv.sh/ref/re.html#re:replace |
33
wxf666 2022-09-05 12:25:00 +08:00
@Jirajine
> xonsh 就是个玩具 xonsh 大概有啥不足呢?我只匆匆看过一眼,没用过 > rename 用 $1 $2 来引用 capture group ,是自己的语言,不是 shell 的 用的是 pcre 吧。sed 也类似(但用的是 posix bre ere ) 他们作为字符串传递,本来就和 shell 没啥关系呀 胶水语言就是这样咯,用最基础的 shell 语法,来描述要用人家的啥东西。。 我觉得你那个 elvish 应该也类似,golang 的正则库支持特性不多( regex101 说的) 想用一些高级特性(如 \p{Han}、a*?、a*+、(?>...)、(?<=...)、(?R)、(?(DEFINE)...) 等),就要导入其他库使用,甚至有自己的语法,不和 golang 未来的正则库兼容 这时候会不会就有人说 elvish 号称一致性,实际有多套正则语法,互不兼容,心智负担…… > 用 shell 构建另一个语言的字符串,你得考虑 shell 的转义(单引号或$符号)、dsl 的转义( /符号)、正则特殊字符的转义 shell 的转义:'$p $a $t \t \e \r \n' 都没问题啊(除了有 ' 字符时,需要用 'aaa'\''bbb' 表示) dsl 的转义:那就看你那个工具的设计好不好咯。sed perl rename 可以用其他符号的:s|http://|https://| 正则特殊字符的转义:这个就是正则的问题了。golang 应该一样要面对 > glob 又是一套类似正则,但又不同的匹配语言 bash 的 glob ,也就 [] ? * {} 之类几个简单的语法吧,比正则简单得多 另外,我瞅了一眼,elvish 也是另外一套语法,且有点繁杂。。 bash:*.[ch]、[a-z].go elvish:*.?[set:ch]、?[range:a-z].go > 引用变量总是需要 quoting 。用 shell 处理包含空格的字符串简直是 nightmare Emm... "$s" 不至于是 nightmare 吧。。 > 你要传多个参数,直接用 list 就行了 其实 bash 也支持 数组 和 哈希 呀。传多个参数,也可以直接用 数组:ls "${array[@]}" > 你要传多个参数,直接用 list 就行了 我好奇 elvish 如何将 一个命令的返回值,split 成多个参数,传递给另一命令?如: apt purge $(dpkg -l | grep ^rc | awk '{print $2}') |
34
Jirajine 2022-09-05 15:42:47 +08:00
@wxf666 parser 太随意,一部分传给 python ,一部分传给 bash ,语义严重不一致。
还是因为缺乏结构化数据类型,只能一边 parse 字符串,一边拼接出特定的字符串给别的程序 parse 。 go/rust 的正则库大差不差,功能完全够了吧,其他“高级特性”实现的话就做不到线性时间复杂度了,而且考虑可读性也不适合用单条正则写。 关键是它标准库有常用字符串和正则函数,这些 bash 根本实现不了。 一堆不同语言的转义,考虑的太多,glob 和正则共用不少符号但语义又不一样,增加心智负担。 elvish 的 glob 简单很多,从文档的长度上就能体现出来。 bash 几乎总是需要 quoting ,如果处理含空格字符串的话,空格有时候作为分隔符,有时候又不是,还有 IFS ,处理起来难写难用且易错。 bash 的数组和 map 那是在 posix sh 上后来加的,二等公民,而且不能表达结构化数据(数组存 map 、map 存数组),也避免不了 word splitting 的糟粕。 你那个命令 elvish 是兼容的,直接 apt purge (dpkg -l | grep '^rc' | awk '{ print $2}') 效果是一样的。 因为 elvish 兼容传统 byte pipe ,期望 chan string 作为输入类型的命令 也会接受字节流输入,并把字节流按换行符 split 。output capture 也会默认做这种转换。 如果不希望这种转换可以用 slurp ,slurp 接受读取 byte pipe 输入原样存入一个 string 里返回。 |
35
hxy100 2022-09-05 16:22:14 +08:00
就这也能起争执,666
|
36
wxf666 2022-09-05 21:22:17 +08:00
@Jirajine 用了些 emoji 快速表明态度
> parser 太随意,一部分传给 python ,一部分传给 bash ,语义严重不一致。 我看它是,但凡 命令 和 参数 中,有出现未定义的标识符,就当作外部命令处理 感觉也说得过去?❓能举些你觉得容易出错的例子吗? > 还是因为缺乏结构化数据类型,只能一边 parse 字符串,一边拼接出特定的字符串给别的程序 parse elvish 能直接传递 list map 给其他命令?从其他命令接收来的 str ,不 parse ,咋变成 list map 的? ❓你是说 xml json 序列化、反序列化 这些库吗? > go/rust 的正则库大差不差,功能完全够了吧 相比 pcre C# 而言,还差很多。😑你这样说,显得人家在不务正业。。 > 其他“高级特性”实现的话就做不到线性时间复杂度了 写应用确实速度快(是因为用 DFA 实现吗?) 但在 交互式 shell 中,更需要功能丰富啊 正则库不支持,❓不就要苦逼地写代码,自己实现相同逻辑了么。。 > 关键是它标准库有常用字符串和正则函数,这些 bash 根本实现不了 ✔️确实,字符串处理是 bash 的弱项。这应该也属于 shell 的基础设施的 正则匹配的话,还是有个 [[ $s =~ regex ]] 可用的 > 一堆不同语言的转义,考虑的太多 🔁再次重复: bash 的 'pattern' 足够好了,连 \ 都是本身的意思:'\' 最多只需考虑 ' ( elvish 也需写成 'str1''str2') > glob 和正则共用不少符号但语义又不一样,增加心智负担。elvish 的 glob 简单很多 🔁再次重复: elvish 的 glob 也用了 ? * ** {} ?[],❓语义不是也和正则不同吗? ❓elvish 的 glob 也比 bash 的复杂呀: bash:*.[ch]、[a-z].go elvish:*.?[set:ch]、?[range:a-z].go > bash 几乎总是需要 quoting ,如果处理含空格字符串的话,空格有时候作为分隔符,有时候又不是,还有 IFS ,处理起来难写难用且易错。 需要作为一个参数:"$s" 需要 word splitting:$s ❓足以应付大多数场景了吧?或者你举些例子? > bash 的 数组和 map ……不能表达结构化数据 ✔️确实,但对于日常交互式使用而言,一般也足够了。再复杂,也适合上脚本了 > 默认按换行符 split 。如果不希望这种转换可以用 slurp 🤔还行 bash 作为一个参数:"$s"、"$(...)" elvish 作为一个参数:$s 、(... | slurp) ❓还是感觉 bash 整体代价较低? ❓elvish 默认是按 \n 切割的。如何像 bash 那样,按 IFS 来切割 (...) 呢? |
37
Jirajine 2022-09-06 07:32:29 +08:00
@wxf666 所以说它不是一个新语言,充其量只能算是类似 ipython 的 ui 。
结构化数据肯定只能在语言内部用,但 bash 是语言内部都没有结构化数据,你就得一直拿字符串糊过来糊过去。 ip --json addr | all (from-json) | each {|i| echo $i[ifname] $i[addr_info][0][local]} 正则搞得太“高级”,不符合 do one thing and do it well 的理念,这些功能自己写代码实现可读性和心智负担都更好,这也是 go/rust/cpp 等语言的正则库只实现一部分特性的原因。 quoting hell 了解一下,如果转义字符也需要转义。。 多打几个字符不代表复杂,看文档长度就知道哪个复杂了,elvish 可没有 extended glob ,特殊字符也很少。 word splitting 我举个最简单的例子: 一个目录里有两个文件: Record.txt Record 02.txt a=$(ls) ; file $a # 这里是写$a 还是"$a"呢? (我知道 ls 不该这样用,这里是演示处理含空格字符串) 日常使用结构化数据非常有用,尤其是数组,上面那个例子在 elvish 里就没有任何问题: var a = (ls) ; file $a word splitting 和 IFS 就是早年 sh 没有数组而发明的 trick 。 其他不需要 IFS 的语言怎么切割,这还用说吗?就像所有高级编程语言一样,用 str:split 函数啊。 另外 elvish 不会对结果做任何分割,是 (...)表达式本身可以 evaluate 成多个值,就像 golang 的多返回值一样。 |
38
wxf666 2022-09-06 11:18:42 +08:00
@Jirajine
> 充其量只能算是类似 ipython 的 ui 无所谓这些概念。🔁还是希望你能举些 xonsh 『语义严重不一致』的例子❓ > 但 bash 是语言内部都没有结构化数据,你就得一直拿字符串糊过来糊过去 ✔️大部分同意。但如果只是 json 的话,jq 这个工具大部分时候还是足够使用的: ip --json addr | jq -r '.[] | .ifname + " " + .addr_info[0].local' > 正则搞得太“高级”,不符合 do one thing and do it well 的理念 我觉得还是『匹配某句法规则的字符串』范畴,且允许描述得更好了,还是符合理念的 换句话说,❓为何 go/rust 的正则库,就是按照“do one thing and do it well”理念设计的、shell 正则库的巅峰呢? ❓不能是 perl 的 pcre 嘛? > 这些功能自己写代码实现可读性和心智负担都更好 🤔我不觉得我会自己实现 \p{Han}、a*?、a*+、(?>)、(?<!),心智负担很大。。 🤔也不觉得 [\u4e00-\u9fa5] 会比 \p{Han} 可读性好(其实前者只是后者的小子集,真实情况前者会很长) > 这也是 go/rust/cpp 等语言的正则库只实现一部分特性的原因 🤔『线性时间复杂度』等特点,是高速应用的需求,但不该是交互式 shell 的 > quoting hell 了解一下,如果转义字符也需要转义。。 🔁再次重复: '\' 中的转义字符,就是它自己,不是转义了 '。若要转义 ': bash:'left'\''right' elvish:'left''right' 实在不行,还有 Here Doc 嘛: cat <<'EOF' !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ EOF > elvish 可没有 extended glob ,特殊字符也很少 bash 默认也不开启 extended glob 。。 ❓要不你举些 bash 的 glob 比 elvish 复杂的例子出来吧 > a=$(ls) ; file $a # 这里是写$a 还是"$a"呢? IFS=$'\n' file $(ls) ❓突然想到,这样是不是就和 elvish 的 (...) 等价了? > 日常使用结构化数据非常有用,尤其是数组 ✔️确实,这些也应该是 shell 的基础设施。bash 能用,但用起来很累: readarray -t arr < <(ls) file "${arr[@]}" |
39
Jirajine 2022-09-06 13:09:56 +08:00
@wxf666 上下文敏感的 parser ,ls -al 是调用命令还是 算术表达式取决于上下文,这种不一致性在复杂情况下结果可想而知,变量名拼写错误会执行外部代码。
jq 就是糊字符串,简单读取一些 json field 倒还好,稍微复杂点的 group_by ,结构变换等就麻烦了,当然做肯定能做,毕竟 jq 自己也有一套“高级”的 dsl 。 脚本里有一大堆 ad-hoc 的 parse 和拼接字符串的代码,难写难读易错还不安全,远远不如直接操作结构化数据。 go/rust 的正则库都是从 RE2 来的,这种设计安全、高效、不会 overflow 、线性匹配时间,详见 https://swtch.com/~rsc/regexp/regexp1.html Unicode script 和 lazy 匹配都是支持的,不支持的只有涉及 look around 和 backreference 的特性,完全不必要而且 overload 的字符更多让正则更难读。 quoting hell 指一次 evaluation 的结果再次被另一种相同或不同的规则 evaluate ,所以需要同时为多种规则 quoting 和转义。如: ssh host touch 'my file.txt' 会创建 my 和 file.txt 两个文件。 bash 就是语言表达能力不足,才不得不把 glob 做的更复杂,另外涉及兼容性等原因有时开了有时又没开更加剧碎片化,zsh 在这方面更为尤甚。 这就是 IFS 和 word splitting 糟糕的地方,数据(变量值)影响语义,在代码的不同地方处理、存储、复制、传递含空格字符串,并保证结果正确是非常麻烦且恶心的。 bash 的 array 不是一般的难用,比如复制 array 到另一个变量: a=('file 01.txt' 'file 02.txt') b=$a b=${a[*]} b="${a[*]}" b=${a[@]} b="${a[@]}" b=( $a ) b=( ${a[*]} ) b=( "${a[*]}" ) b=( ${a[@]} ) 以上这些 b 的值都是什么? |
40
wxf666 2022-09-06 14:21:44 +08:00
@Jirajine
> 变量名拼写错误会执行外部代码 🤔我还没怎么用过 xonsh ,也不知这种情况严不严重 > 脚本里有一大堆 ad-hoc 的 parse 和拼接字符串的代码,难写难读易错还不安全,远远不如直接操作结构化数据 ✔️写脚本我就不用 bash 这坑爹玩意儿了,换个 Python 不香嘛。。 > 正则 🤔我还是坚持:交互式 shell 需要功能强大的正则 > quoting hell 指一次 evaluation 的结果再次被另一种相同或不同的规则 evaluate ,所以需要同时为多种规则 quoting 和转义 ✔️噢,这种啊,确实绕脑袋 ❓elvish 是咋解决的? > glob 🔁我还是不知道你说的,bash 的 glob 比 elvish 复杂,是啥意思。。❓可以举些例子嘛? > 这就是 IFS 和 word splitting 糟糕的地方,数据(变量值)影响语义,在代码的不同地方处理、存储、复制、传递含空格字符串,并保证结果正确是非常麻烦且恶心的 🔁IFS=$'\n' 后,❓不就可以像 elvish 那样,不用处理啥空格了嘛? 需要一个参数时:"$s"、"$(...)" 需要每行作为一个参数时:$s 、$(...) > bash 的 array 不是一般的难用 ✔️知道 bash 的 array 坑多。反正我一般绕过那些奇奇怪怪的用法,老老实实 "${arr[@]}" 之类的。。 我记得好像 ${arr[*]} 还是 "${arr[*]}" 来着,和 $* "$*" 有不同。。 |
41
aloxaf 2022-09-06 15:15:12 +08:00
你俩竟然还在争论
说实话传统 shell 再难用也没办法,地位已经根深蒂固了。新兴 shell 再吹也没用,无论如何都入不了主流(除了 pwsh 那种捆绑的)。 @Jirajine #39 > bash 就是语言表达能力不足,才不得不把 glob 做的更复杂 bash 的 glob 说实话不算复杂,屎上雕花的 zsh 那才是……怎么说呢,每次看到那些占满整行的单条表达式,都令我对作者肃然起敬 @wxf666 #40 > 🔁IFS=$'\n' 后,❓不就可以像 elvish 那样,不用处理啥空格了嘛? 这样未必不出问题,毕竟 \n 也是个合法的,可能出现在任意地方的字符。 我觉得 word splitting 糟糕的点主要在于——它是全局的、隐式的,这就导致了它成为坑人的好手。 |
42
wxf666 2022-09-06 17:21:30 +08:00
@aloxaf 算交流吧,都一起骂了 bash 的难用的地方,@Jirajine 也介绍了 elvish 优越之处,我也有自己的保留意见
感觉我还能接受新鲜事物。不写脚本的话,尝试换下 shell 也是可以的(反正就自己用而已。好用就赚,难用就换~) 听你这么一说,会不会 @Jirajine 说的『 bash 的 glob 复杂』,其实是『 zsh 的 glob 复杂』的意思。。 原本我思来想去,即使算上 extended glob ,bash 的 glob 也和复杂沾不上边儿才对。。 elvish 不也是按照 \n 切割 (...) 嘛。。 反正被折磨多后,一般都用 "..." 包裹住就是了(然而还有个 ! 。。) |
43
Jirajine 2022-09-06 23:08:00 +08:00
@wxf666 shell 的 变量 expansion 可以说是最糟糕的设计之一,一个变量的值,与如何引用它有关。而 IFS 就是控制如何引用变量的方式,所以非常易错。每当你引用含空格字符串的时候,都得设置 IFS ,包括变量赋值、复制等,操作其他字符串的时候还得再改回去。
elvish 在这方面和所有正常的编程语言一样:变量的值是固定的,不允许在引用变量时自定义各种奇奇怪怪的 evaluate 的方式,因而和 Python 等正常编程语言一样,evaluate 时不需要 quoting 。 elvish 不会更改你的变量内容,只是为了让使用传统*nix 命令行工具的 byte 输入输出格式更方便,很多接受多个 string 对象管道输入的命令(包括 (..) 输出捕获),也会接受 byte 流,并默认将 byte 流按换行符分割后作为多个 string 输入。其实这也是传统*nix 命令行工具约定俗成的格式,只不过 evlish 里真正有类型了而已。默认相当于 from-lines ,对于需要其他格式的输入则可以用 from-json (从 byte 流读取输入并反序列化 json 成结构化对象)、slurp (从 byte 流读取所有数据并存入一个 string 对象里输出)等等。 |