Linux

用於文本處理的 sed 程式碼理解

  • June 7, 2017

誰能在下面的sed程式碼中解釋一下

sed -n '
/Policy Name:/! d
   s/.*:\s\+//
   h
   :1
   n
   /Active:\s*no/d
   /HW\//!b1
   :2
   s/.*\s\(\S*\)\s*/\1/
   G
   s/\n/\t/p
   n
   /^\s*$\|Include:/! b2
   '

我想編輯以添加“策略類型:”資訊,當我用“策略名稱:”替換它時它工作正常,但是當我添加如下部分時它顯然不起作用,因為我在不理解的情況下嘗試它。

sed -n '
/Policy Name:/! d
   s/.*:\s\+//
   h
   :1
   n
/Policy Type:/! d
   s/.*:\s\+//
   h
   :1
   n
   /Active:\s*no/d
   /HW\//!b1
   :2
   s/.*\s\(\S*\)\s*/\1/
   G
   s/\n/\t/p
   n
   /^\s*$\|Include:/! b2
   '

我也有一個來自同一論壇的 AIX 等效程式碼的解決方案,我需要理解它才能編輯它以添加策略類型。

# define constants
SPC=`echo x | tr x '\040'`
TAB=`echo x | tr x '\011'`
NL=

# custom regex for...
s="[$SPC$TAB]";   # horizontal whitespace
S="[^$SPC$TAB]";  # non-whitespace

# POSIX compliant sed code...
sed -ne "
  /Policy Name:/!d

  s/.*:$s\{1,\}//
  h

  :1
     n
     /Active:$s*no/d
  /HW\//!b1

  :2
     s/.*$s\($S*\)$s*/\1/
     G
     s/\n/$TAB/p
     n
     /^$s*\$/d
     /Include:/d
  b2
"  yourfile

輸入文件

Policy Name:       Today

 Policy Type:       Standard
 Active:              yes
 Effective date:      01/24/2014 11:17:05
 Client Encrypt:      no
 LC/CY/Custmr:  EU         NY  Cindy
                BU         CA  Victor
                GU         MI  Bob
 Include:
Policy Name:       Tomorrow

 Policy Type:       Oracle
 Active:              yes
 Effective date:      01/26/2014 11:17:05
 Client Encrypt:      no
 LC/CY/Custmr:  MU         LA  Martha
                EU         CA  Sam
 Include:
Policy Name:       Yesterday

 Policy Type:       Oracle
 Active:              no
 Effective date:      01/21/2014 11:17:05
 Client Encrypt:      no
 LC/CY/Custmr:  NV         IL  Joe

 Include:`

期望的輸出

Cindy    Today     Standard
Victor   Today     Standard
Bob      Today     Standard
Martha   Tomorrow  Oracle
Sam      Tomorrow  Oracle

好的,讓我們一步一步來:

sed -n '

除非被告知,否則該-n選項不會輸出任何內容sed

/Policy Name:/! d

所有不包含的行Policy name:都會被刪除。腳本的其餘部分僅在以下循環中處理。

s/.*:\s\+//
h

這將刪除所有內容,直到:空格和尾隨空格,並將其餘部分放在保持緩衝區中以備後用。

:1
n

這是讀取新行的循環的開始

/Active:\s*no/d

刪除了具有該模式的行,因此顯然對不活動的行沒有興趣

/HW\//!b1

現在,我們循環到:1如果該行不包含HW/

:2
s/.*\s\(\S*\)\s*/\1/

下一個循環的開始,刪除除最後一個非空白序列之外的所有內容。

G
s/\n/\t/p

然後附加保存在保留緩衝區中的策略名稱,用製表符分隔並列印該行

n
/^\s*$\|Include:/! b2
'

這將在下一行重複,直到我們達到給定的模式。

您應該注意,這是高度不可移植的程式碼,不會在許多sed版本上執行。

**編輯:**要將策略類型添加為第三列,您應該在Active:檢查之前或之後將此行添加到腳本中:

/Policy Type:/{s/.*:\s*//;H;}

即:如果該行包含所述字元串,則執行 . 之間的命令{}。這些命令刪除了直到:和尾隨空格的部分,並將該行的其餘部分(應該包含策略類型)附加到保留緩衝區。因此,保持緩衝區包含策略名稱和類型,由換行符分隔。所以當我們追加這個時G,會有兩個換行符被替換,所以替換命令需要獲取g標誌來替換所有出現的:

s/\n/\t/gp

AIX 腳本基本相同,但避免了對正則表達式的 GNU 擴展。主要是使用變數來匹配空格或製表符,因為\t不適用於所有sed口味,以及+“一個或多個”需要替換為\{1,\}

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