題 sed:提取URL查詢字符串中鍵值對的值


我正在嘗試使用sed來提取URL查詢字符串中眾多鍵值對之一的值部分

這就是我想要的:

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's@^https?://(www.)?youtube.com/(watch\\?)?.*?v(=|/)([a-zA-Z0-9\-_]*)(&.*)?$@$4@'

但它總是按原樣輸出輸入的URL。

我究竟做錯了什麼?

更新1

澄清一些問題:

  1. 正則表達式比它必須更複雜,因為我也試圖檢查輸入的有效性並僅在輸入有效時生成輸出。所以更嚴格的比賽。
  2. 所需的輸出是查詢字符串中鍵'v'的值。
  3. 一直無法找到版本 sed 我正在使用它,但它是Mac OS X(10.7.5)附帶的那個。
  4. 在我的版本中 sed $ 1,$ 2等似乎是匹配,\ 1,\ 2等給出錯誤: sed: 1: "s@^https?://(www.)?yout ...": \4 not defined in the RE  不正確! 正如我後來發現的那樣。抱歉造成混亂。

更新2

已經更新了 sed 根據以下@slhck的建議,讓它更具體,但問題仍然像以前一樣。

更新3

基於 man 這個版本的頁面 sed 看來這是一個BSD風格的版本。


4
2018-06-04 12:48


起源


你想要的產量是多少? - Endoro
@Endoro我只能猜測,因為這裡的正則表達式比它必須更複雜,但是我要說因為OP想要第四個捕獲組,所以他們想要之間的一切 v= 而下一個 &,所以視頻ID。 - slhck
@Endoro:我在上面原始問題的更新中回答了這兩點。感謝您尋求澄清。 - markvgti
@markvgti - 如果您繼續提出問題,請澄清您使用的操作系統和其他程序。 - Endoro


答案:


更簡單,如果你只是想要的話 abc

 echo 'http://www.youtube.com/watch?v=abc&g=xyz' | awk -F'[=&]' '{print $2}'

如果你想要的話 xyz :

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | awk -F'[=&]' '{print $4}'

說明:

  • awk :是一種腳本語言,可以逐行自動處理輸入文件,將每一行拆分為字段。因此,當您處理文件時 awk,對於每一行,第一個字段是 $1, 第二 $2 等等 $N。默認情況下 awk 使用空格作為字段分隔符。

  • -F'[=&]' : -F 用於將字段分隔符從空格更改為其他內容。在這種情況下,我給它一個


11
2018-06-04 13:35



很酷,這個有效!唷!這意味著我必須學會使用 awk 現在: - (...謝謝,但是我要推遲將此標記為已接受的答案,希望藉助我可以調試的幫助 sed。很多,非常感謝。 - markvgti
@markvgti事情是 sed 在捕捉模式方面,它不是最好的工具,它非常強大,速度快 能夠 做到這一點,但它比必要的更複雜。我補充說明瞭如何 awk 命令工作,您可能會發現現在更容易理解。我還加了一個 Perl 和a cut 解決方案只是為了完整性:)。 - terdon
我已將您的答案標記為已接受的答案,即使這不是我問題的直接答案。你的答案解釋如此之多,並提供瞭如此多的知識,我認為值得強調。謝謝!運用 sed 本質上是一個例子:“如果你擁有的只是一把錘子,每個問題看起來都像釘子一樣” - 不願意學習更多新東西但是 awk 看起來相當容易,所以也許值得花時間投資。 - markvgti
在* nix世界中的@markvgti,你永遠不會有錘子,所有* nix系統都將安裝sed,awk和perl。 - terdon


如果你需要“xyz”試試這個(GNU sed):

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's/.*=\([[:alnum:]]*\).*/\1/'

2
2018-06-04 13:24



要小心 \w 與POSIX不兼容,因此該命令不可移植。 - slhck
你是對的,我改成了 [[:alnum:]], 謝謝! - Endoro
@Endoro你的回答讓我走上正確的道路(謝謝!),我能夠想出所需的東西 sed 命令(雖然我需要更具體的東西 [[:alnum:]])並將其作為答案添加。 - markvgti


試驗 sed 根據@Endoro和@slhck給出的答案,我找到了最終答案(我想要的答案)。這對我的版本有用 sed 在Mac OS X上(10.7.5):

echo 'http://www.youtube.com/watch?v=dnCkNz_xrpg' | sed -E 's@https?://(www\.)?youtube.com/(watch\?).*v=([-_a-zA-Z0-9]*).*@\3@'

說明:

  1. -E 就是要做 sed 使用擴展RE。在其他版本的 sed  -r 可能是等價的選擇。
  2. 看似比需要更複雜的RE還要驗證這是一個有效的YouTube鏈接。根據需要修改此RE的開頭部分(例如, https?://(www\.)?example.com/(.*\?).*key=([^&]*).*
  3. \3 匹配括號中的第三個表達式並將其打印為答案/匹配(這就是我想要的)。
  4. 使用's @@@'而不是通常的///',這樣我就不必逃避許多正斜杠(\)在URL中。

希望這也有助於其他人,因為我得到了幫助。


2
2018-06-05 04:39



正如我在回答中提到的, -E 是BSD sed 擴展正則表達式的選項,所以我認為你在OS X上? -r 用於GNU sed 這是Linux的標準配置。 - slhck
@slhck是的,正如我在問題的更新1中提到的,我在OS X(10.7.5)。 - markvgti
沒看到你的編輯。很高興你弄清楚了! - slhck


如果你真的只想要視頻ID - 那麼,之間的任何東西 v= 而下一個 &  - 只需使用:

sed -r 's/.*v=([[:alnum:]]*).*/\1/'

這是你的命令有什麼問題:

  • -r 需要使用擴展正則表達式。如果你把它留下來, sed 從字面上解釋括號,因此不會有任何匹配組。有了BSD sed, 使用 -E相反的選擇。

  • 你用 $1 引用匹配,但你應該使用 \1$1 實際上是一個傳遞給當前腳本的shell參數。

  • 你應該使用像這樣的字符類 [[:alnum:]] (要么 [a-zA-Z0-9_] 取決於如何設置ID)以匹配參數值,否則下一個 & 也將被捕獲。正則表達式是貪婪的,只會匹配 abc&g=xyz 如果你使用 .*?,因為BRE / ERE不支持延遲量化,只有Perl正則表達式或其他“現代”口味。


1
2018-06-04 13:14



如上面的更新,1)無法找到sed版本,2)\ 1,\ 2等拋出錯誤。這個版本 sed 說 -r 是一個非法的論點。 - markvgti
即使我改變了 (.*?) 期望的匹配 ([a-zA-Z0-9\-_]*) (因為此值是Base64編碼的),它仍然不起作用。關於使比賽更具體的好建議。 - markvgti


它始終顯示URL,因為SED與其不匹配。

    echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's!^http://www.youtube.com/watch\?\(.*=.*\)&\(.*=.*\)!\1!'

會顯示 V = ABC


0
2017-09-19 03:18