[问题] 这个 sed-缩网址程式何时会爆炸?

楼主: cuello (cuello)   2020-11-04 06:52:13
#!/bin/sh
#
# 1604436674 created for testing in Linux/PTT
#
# 这是个 YouTube 缩网址的 one-liner. 必须很 portable.
# 我已测试过各种不同形状的水管 url's 例如:
#
# /v/<VID>
# watch?v=<VID>
# embed/<VID>?rel=0
# watch?argv=xyz&v=<VID>
# watch?v=<VID>&list=PLDB852818BF378DAC
# watch?v=<VID>&feature=related
# watch?argv=xyz&v=<VID>
# watch?v=<VID>&feature=feedrec_grec_index
# user/IngridMichaelsonVEVO#p/a/u/1/<VID>
# v/<VID>?fs=1&amp;hl=en_US&amp;rel=0
# watch?v=<VID>#t=0m10s
# embed/<VID>?rel=0
# watch?v=<VID>
# http://youtu.be/<VID> (idempotent)
#
# 能不能帮忙看看还有哪些 url's 会出错, 并帮忙想办法?
#
# 我本来不喜欢缩网址的, 因为不知道有效期限多久...
# 但如果我没误解的话, youtu.be 是水管自家的,
# 而且保留了原始的影片 ID (确定都是11个字吗?).
# 所以还可以接受.
#
# 解说:
#
# 0. 它必须尽可能 portable, 不管什么系统, 必须随抄即用
# 谁有 Solaris, SunOS, OsX, Ultrix, AIX, ... 拜托!
# 我只是很好奇, 它能有多广的 portability.
#
# 1. 请忽视与 termux 有关的东西, 那是让手机也可以用的,
#
# 2. youtu() 就已经是个充份的 one-liner.
# 为了应付可能出现的杂七杂八的选项及形态
# 我决定撷取 \1. protocol 跟 \2. video_id
# 然后忽略掉其它可能出现的所有东西.
#
# 3. 为方便测试, 所以它要可以从 X-clipborad 读取,
# 由 stdin 读取, 也可以由指令行读取.
#
# 4. 用了 sed(1) tr(1) grep(1) xsel(1) termux-clipboard-get(1)
#
# 5. 1604555294 新增, 原本的 -e 's/$/\n/' | tr -s '\n' 是为了确保
# 行尾起码有一个 newline, 而且只有一个. 这也是为了使用上方便.
youtu()
{
# sed -e 's|^\(http.\?\):.*[/vd]\{0,1\}[0-9vd][/=]\([0-9a-zA-Z_-]\{11\}\).*$|\1://youtu.be/\2|' -e 's/$/\n/' | tr -s '\n'
# 哇
作者: Typebrook (Pham)   2020-11-04 09:04:00
还没看完,不过要大量用到Regex的话,sed建议加-E这样很多地方就不用加反斜线了然后我会这样写:sed -Ee '[email protected](http|https)://.*[/=]([0-9a-zA-Z_-]{11}).*@\1://youtu.be/\[email protected]'如果确定都是11码后9码以上,vd那段其实不用加或者也可以把{11}改成{11,}
作者: bitlife (BIT一生)   2020-11-04 09:27:00
你要找何时会爆是要找实务上可见的,还是故意弄出会爆但实务上不(太可能)会出现的?
作者: lantw44 (#######################)   2020-11-05 00:03:00
shell script 部分的 portability 可以先跑 shellcheck看看有没有问题,而一楼说的 sed -E 在 POSIX 没有,所以可以猜想如果有的系统只做 POSIX 那就不能用 sed -E。实际测试这个 script 在 FreeBSD 执行成功但结果有误,因为 FreeBSD 的 sed 不支援 \? 和 \n。
作者: rickieyang (Rickie Yang)   2020-11-05 15:30:00
B false?
楼主: cuello (cuello)   2020-11-05 15:59:00
是说,我一直相信,B false 的情况,跟 C 一样,evaluation 会停下来,return false 的值...对于 Bourne shell 而言,我一直保持这种态度,现在居然要被推翻了吗? :(因为答案是 false 已经得到了就不继续 evaluate C 了有谁在哪个系统上,哪个 shell 会继续做 C 吗?
作者: bitlife (BIT一生)   2020-11-05 16:19:00
假设A true,但如果B为false,就会去执行C啊(后方命令会印出hello) $ true && false || echo hello
楼主: cuello (cuello)   2020-11-05 17:12:00
对对对,我是错的,头壳坏掉了才会这样
作者: rickieyang (Rickie Yang)   2020-11-06 00:16:00
没有 xsel, uname 会得到 Darwinmac 要拿剪贴簿内容可以用 pbpaste
作者: Gold740716 (项为之强)   2020-11-06 21:19:00
我觉得没必要全部写在同一行,你可以把 sed 分成很多行尤其是考虑到可读性我看 freebsd 的 sed 手册是写支援 `\n` 的啊?https://www.freebsd.org/cgi/man.cgi?query=sed
作者: lantw44 (#######################)   2020-11-07 13:29:00
手册上指的应该是可以用 \n 配对输入,但不能用在输出。根据 POSIX 的说法,若要在 s 指令中输出换行,则要使用反斜线加真正的换行字符。
作者: ucrxzero (RX-0)   2020-11-08 00:12:00
是说A &&(B||!B )||C其实就行啦你会以为A&&B||C可行是因为 通常BC都不会当表达式了不会care $?是否为0
楼主: cuello (cuello)   2020-11-08 09:34:00
因为我B常是在做 assignment,用惯了开始错觉吧所以不要常用成语,idiom 用多了会变 idiot! :)
作者: bitlife (BIT一生)   2020-11-08 13:22:00
用 A && (B||true) || C会更好,避免B不是idempotent以及省运算时间
作者: Gold740716 (项为之强)   2020-11-08 15:08:00
但要用 {} ,用 () 会在子 shell 里赋值没有用
作者: bitlife (BIT一生)   2020-11-08 15:55:00
查了一下, (list) 的return value是list的值,实际用前述true false命令测试也确实如此true && (false||true) || echo hello 不会印hellotrue && (false||false) || echo hello 会印hello喔,我懂了,是指前面u大说的拿来assignment确实一律用 {} 比较不会搞混
作者: ucrxzero (RX-0)   2020-11-08 18:26:00
楼上大大是对的
作者: yoche2000 (Sushi Desu! 在下寿司)   2020-11-09 01:19:00
推 学习了

Links booklink

Contact Us: admin [ a t ] ucptt.com