簡體   English   中英

如何在sed中提取嵌套括號?

[英]How to extract nested parentheses in sed?

我正在嘗試使用sed提取空格分隔的列。 這是一個帶有ps的示例:

$ ps | sed -n -E "s/^(\s*([^\s]+)){4}.*$/\0/p"
  PID TTY          TIME CMD
 8446 pts/185  00:00:00 ps
 8447 pts/185  00:00:00 sed
54326 pts/185  00:00:00 bash
$ ps | sed -n -E "s/^(\s*([^\s]+)){4}.*$/\1/p"
D
t
t
t

為什么會這樣? 如何指定嵌套括號?


我想獲取 PID 列(在本例中)。


我發現我也無法處理非嵌套括號:

$ ps > out.txt
$ cat out.txt
  PID TTY          TIME CMD
14819 pts/185  00:00:00 ps
54326 pts/185  00:00:00 bash
$ cat out.txt | sed -n -E "s/^\s*([^\s]+)\s*([^\s]+)\s*([^\s]+)\s*([^\s]+).*$/\2/p"
C


$ 

在最后一種情況下,它打印帶有C和 2 個空行的行。

為什么???

假設原始文件是

a1  a2 a3 a4
b1 b2 b3 b4
c1  c2 c3 c4
d1 d2 d3 d4

(如果有前導空格,請在單獨的操作中將其刪除, 's/^ *//'

沒有擴展的正則表達式,你可以這樣做:

sed 's/\([^ ][^ ]* *\)\{3\}.*/\1/'

這將產生

a3
b3
c3
d3

擴展的正則表達式可能會使這更清晰一些,但並非所有實現都支持反向引用,因此邏輯會更復雜一些。

首先,請避免使用雙引號,除非您希望 shell 對其進行解釋(請參閱https://mywiki.wooledge.org/Quotes

awk更適合現場處理,但我會嘗試提供帶有解釋的sed解決方案(假設使用GNU sed作為\\s

$ sed -n -E 's/^(\s*([^\s]+)){4}.*$/\1/p' ip.txt
D
t
t
t
  • ^線錨的開始
  • [^\\s]這不會如你所願,它會匹配\\s以外s字符。 \\s , \\S , \\w\\W不被字符類中的sed識別,在這種情況下,您可以簡單地使用\\S
  • (\\s*([^\\s]+))您可能打算使用兩個捕獲組僅捕獲字段值
  • {4}但是,當使用量詞時,只有最后一個匹配項可用於反向引用,其他匹配項將被覆蓋。 (進一步閱讀: https : //www.regular-expressions.info/captureall.html
  • 因為像CMD這樣的\\s*字符串在上述情況下匹配為多個字段
  • 另外,不確定為什么要使用-np而不是將它們排除在外

要獲取特定列,我會使用:

$ sed -E 's/^\s*(\S+).*/\1/' ip.txt
PID
8446
8447
54326

$ sed -E 's/^\s*\S+\s+(\S+).*/\1/' ip.txt
TTY
pts/185
pts/185
pts/185

$ sed -E 's/^\s*\S+\s+\S+\s+(\S+).*/\1/' ip.txt
TIME
00:00:00
00:00:00
00:00:00

這給了我們以下通用公式:

$ sed -E 's/^\s*(\S+\s+){0}(\S+).*/\2/' ip.txt
PID
8446
8447
54326
$ sed -E 's/^\s*(\S+\s+){1}(\S+).*/\2/' ip.txt
TTY
pts/185
pts/185
pts/185

這可能對你有用(GNU sed):

sed -nE 's/\S+/\n&\n/1;s/.*\n(.*)\n.*/\1/p' file

這用換行符包圍第 n 列(在此示例中為第 1 列),然后使用模式匹配刪除任一側的字段和換行符。

或者:

sed -nE 's/^(\s*(\S+)){4}.*/\2/p' file

這將返回第 4 個字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM