這個 sed-縮網址程式何時會爆炸? - Linux

Table of Contents

#!/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'
# 哇-- 這行那麼長不知道會不會壞掉....
#
# 1604555294 更新, 上面那一行到 FreeBSD 就燒了, 先斷成兩行吧 (lantw44)

# sed 's|^\(http[s]\{0,1\}\):.*[/vd]\{0,1\}[0-9vd][/=]\([0-9a-zA-Z_-]\{11\}\).*$|\1://youtu.be/\2\
#|' | tr -s '\n'

# 1604671459 找了 awk 幫忙來確保 one & only one newline
sed 's|^\(http[s]\{0,1\}\):.*[/vd]\{0,1\}[0-9vd][/=]\([0-9a-zA-Z_-]\{11\}\).*$|\1://youtu.be/\2|' | awk 1

}

if [ -t 0 ] # priority: stdin > "$1" > X-clipboard
then
# echo "$HOME" | grep -q termux && XGET="termux-clipboard-get" || XGET="xsel"
# [ "$1" ] && echo "$1" | youtu || $XGET | youtu
# 1604570722 還是改一下吧, 以上兩行是錯的, A && B || C 不是 if-then-else
# (contributors: lantw44 rickieyang bitlife)

# if echo "$HOME" | grep -q termux
# then
# XGET="termux-clipboard-get"
# else
# XGET="xsel"
# fi
#
# if [ "$1" ]
# then
# echo "$1" | youtu
# else
# $XGET | youtu
# fi

# 1604671459 讓它在 Mac 上也會動 (rickieyang)
if [ "$1" ]
then
echo "$1" | youtu
else # termux > Mac > X11
XGET="xsel"
uname | grep -q "Darwin" && XGET="pbpaste"
echo "$HOME" | grep -q "termux" && XGET="termux-clipboard-get"

$XGET | youtu
fi

else
youtu
fi



--

All Comments

Eartha avatarEartha2020-11-05
還沒看完,不過要大量用到Regex的話,sed建議加-E
Rosalind avatarRosalind2020-11-07
這樣很多地方就不用加反斜線了
Una avatarUna2020-11-08
然後我會這樣寫:
sed -Ee 's@(http|https)://.*[/=]([0-9a-zA-Z_-]{11})
Donna avatarDonna2020-11-10
.*@\1://youtu.be/\2@'
如果確定都是11碼後9碼以上,vd那段其實不用加
Eartha avatarEartha2020-11-11
或者也可以把{11}改成{11,}
Annie avatarAnnie2020-11-13
你要找何時會爆是要找實務上可見的,還是故意弄出會爆但實
Elma avatarElma2020-11-14
務上不(太可能)會出現的?
Yuri avatarYuri2020-11-16
shell script 部分的 portability 可以先跑 shellcheck
Mason avatarMason2020-11-18
看看有沒有問題,而一樓說的 sed -E 在 POSIX 沒有,所以
Blanche avatarBlanche2020-11-19
可以猜想如果有的系統只做 POSIX 那就不能用 sed -E。
Todd Johnson avatarTodd Johnson2020-11-21
實際測試這個 script 在 FreeBSD 執行成功但結果有誤,因
Valerie avatarValerie2020-11-22
為 FreeBSD 的 sed 不支援 \? 和 \n。
Dora avatarDora2020-11-24
B false?
Sandy avatarSandy2020-11-25
是說,我一直相信,B false 的情況,跟 C 一樣,
evaluation 會停下來,return false 的值...
Oliver avatarOliver2020-11-27
對於 Bourne shell 而言,我一直保持這種態度,
現在居然要被推翻了嗎? :(
Lydia avatarLydia2020-11-28
因為答案是 false 已經得到了
就不繼續 evaluate C 了
有誰在哪個系統上,哪個 shell 會繼續做 C 嗎?
Dorothy avatarDorothy2020-11-30
假設A true,但如果B為false,就會去執行C啊
Jacob avatarJacob2020-12-01
(後方命令會印出hello) $ true && false || echo hello
Anthony avatarAnthony2020-12-03
對對對,我是錯的,頭殼壞掉了才會這樣
Irma avatarIrma2020-12-04
沒有 xsel, uname 會得到 Darwin
Belly avatarBelly2020-12-06
mac 要拿剪貼簿內容可以用 pbpaste
Olga avatarOlga2020-12-07
我覺得沒必要全部寫在同一行,你可以把 sed 分成很多
Kelly avatarKelly2020-12-09

尤其是考慮到可讀性
Susan avatarSusan2020-12-10
我看 freebsd 的 sed 手冊是寫支援 `\n` 的啊?
https://www.freebsd.org/cgi/man.cgi?query=sed
Madame avatarMadame2020-12-12
手冊上指的應該是可以用 \n 配對輸入,但不能用在輸出。
Megan avatarMegan2020-12-13
根據 POSIX 的說法,若要在 s 指令中輸出換行,則要使用
Joe avatarJoe2020-12-15
反斜線加真正的換行字元。
Una avatarUna2020-12-16
推文的時候我是用 N 測試的,可以 match 到。我也試過輸
Olivia avatarOlivia2020-12-18
出換行,用 \ 加換行字元是可以輸出的。
Edwina avatarEdwina2020-12-20
是說A &&(B||!B )||C其實就行啦
Elma avatarElma2020-12-21
你會以為A&&B||C可行是因為 通常BC都不會當表達式了不
會care $?是否為0
Daniel avatarDaniel2020-12-23
因為我B常是在做 assignment,用慣了開始錯覺吧
所以不要常用成語,idiom 用多了會變 idiot! :)
George avatarGeorge2020-12-24
用 A && (B||true) || C會更好,避免B不是idempotent以及
省運算時間
Bethany avatarBethany2020-12-26
但要用 {} ,用 () 會在子 shell 裡賦值沒有用
Una avatarUna2020-12-27
查了一下, (list) 的return value是list的值,實際用前述
John avatarJohn2020-12-29
true false命令測試也確實如此
Daph Bay avatarDaph Bay2020-12-30
true && (false||true) || echo hello 不會印hello
Ina avatarIna2021-01-01
true && (false||false) || echo hello 會印hello
Candice avatarCandice2021-01-02
喔,我懂了,是指前面u大說的拿來assignment
Barb Cronin avatarBarb Cronin2021-01-04
確實一律用 {} 比較不會搞混
Harry avatarHarry2021-01-05
樓上大大是對的
Barb Cronin avatarBarb Cronin2021-01-07
推 學習了