[問題] 這個 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