Bash

傳遞給“sed -e”的這個腳本的功能是什麼?

  • September 18, 2022

TL;DR- 下面的模式中發生了很多事情sed,我不確定離散的部分是如何組合成一個整體命令的。


重擊版本:GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)

我正在通過逐個文件閱讀 RBENV 程式碼庫文件來學習 shell 腳本,並且我遇到了rbenv-help包含此函式定義的文件:

extract_initial_comment_block() {
 sed -ne "
   /^#/ !{
     q
   }

   s/^#$/# /

   /^# / {
     s/^# //
     p
   }
 "
}

我看到如何在程式碼中進一步呼叫此函式,所以我知道它的第一個 arg 是文件名:

extract_initial_comment_block < "$filename" | collect_documentation

從這裡我可以看到由“$filename”表示的文件被作為標準輸入提供給sed命令。就我的問題而言,連鎖功能“collect_documentation”是無關緊要的。

我還從函式的名稱中得知,它的目的是獲取這樣的文件並返回其摘要和使用註釋,即連結文件的第 2-14 行。但是,我還沒有測試過這個理論,所以我可能不是 100% 正確的。

此外,我從這個 StackExchange 答案中知道,標誌的目的-e是告訴sed將後續字元串解釋為命令(或由換行符分隔的命令集合?)。因此,它的主體看起來extract_initial_comment_block包含 3 個單獨的腳本,sed以便按順序進行解釋。相同的 StackExchange 答案說{...}用於將命令組合在一起,但我不確定這是否是這個正則表達式(這些正則表達式?)中發生的事情。

據我所知,這裡有 3 個腳本sed

   /^#/ !{
     q
   }
   s/^#$/# /
   /^# / {
     s/^# //
     p
   }

但是,即使在這些腳本中的每一個中,都使用了一些我無法辨識的模式(例如^#和),即使在利用了Linux Data Project之類的資源之後也是如此。似乎有很多動人的部分,我不確定每個腳本是如何組合成成品的。!{ q }

我試圖以盡可能清晰的方式走過我的思考過程。到目前為止,我的構想正確嗎?如果不是,我在哪裡偏離了航線?如果是,我如何推斷傳遞給的每個命令的含義sed

/^#/ !{
      q
    }

斜線之間的部分是正則表達式,其中^表示字元串的開頭,#只是字元本身。該模式選擇執行相關命令的行。尾隨!反轉匹配的意義,q是退出的命令。因此,當 sed 程序看到以註釋標記開頭的行時,它會退出該程序#

 s/^#$/# /

s/a/b/ s用 b 代替 a,^是行首,$行尾,#是它自己。所以這改變了一行,只有一個單獨的##+空格。

/^# / {
  s/^# //
  p
}

如果該行以 a#和空格 ( /^# /) 開頭,則將和空格替換為#空 ( s/^# //) 並列印該行 ( p)。這是以前的替換派上用場的地方。

sed的-n選項(在命令的開頭)告訴 sed在執行腳本後列印該行,預設情況下會這樣做。

請注意,腳本會忽略以 a 開頭且#後面沒有空格的行,包括以它開頭的 hashbang 行#!,告訴作業系統要為腳本使用哪個解釋器。可能是故意的,但可能會隱藏其他一些行。

例如

#!/bin/sh
# some script
#
#this is ignored
# this prints

# this doesn't print any more
whatever

變成

some script

this prints

引用自:https://unix.stackexchange.com/questions/717738