我有一系列的線條形式。
Agenda HR-1 Presented by XYZ
HR-2 Debate-1 - All
HR-3 Debate-2 - All
(Cov-4) Conclusion
每一行都有一個 (sed) 模式的 ID [A-Za-z]\+-[0-9]\+
,即一個或多個字母後面跟著一個破折號 (-),後面跟著一個或多個數字。它們出現在隊列中的任何位置。
我需要提取 ID。我的想法是.*
在開頭和結尾粘貼 a並打印\1
,但我無法讓它工作。
這回覆說 sed 僅替換第一個匹配項,這是正確的:
$ cat /tmp/scratch/x | sed -n 's/\<\([A-Za-z]\+-[0-9]\+\)/ID:\1/p'
Agenda ID:HR-1 Presented by XYZ
ID:HR-2 Debate-1 - All
ID:HR-3 Debate-2 - All
(ID:Cov-4) Conclusion
但當然,.*
一開始會貪婪地轉到最後一場比賽:
$ cat /tmp/scratch/x | sed -n 's/.*\<\([A-Za-z]\+-[0-9]\+\).*/ID:\1/p'
ID:HR-1
ID:Debate-1
ID:Debate-2
ID:Cov-4
我能想到的唯一方法sed
是在一個命令中的 ID 周圍添加標記,然後使用另一個命令進行提取,如下所示。
在 sed 中是否有更好的方法來做到這一點?
$ cat x | sed -n 's/\<\([A-Za-z]\+-[0-9]\+\)/<id>\1<~id>/;s/.*<id>\(.*\)<~id>.*/\1/;p'
HR-1
HR-2
HR-3
Cov-4
答案1
使用 GNU awk
,嘗試:
gawk -v FPAT='[A-Za-z]+-[0-9]+' '$1{print $1}' FILE
或者:
gawk -v FPAT='[A-Za-z]+-[0-9]+' '$0=$1' FILE
答案2
與sed
,嘗試:
<FILE sed -En '/([[:alpha:]]+-[0-9]+).*/{ s//:\1/; s/.*://p; }'
- 刪除所需匹配項後的所有內容
- 現在匹配位於每一行的末尾——這可以通過多種方式處理
- 上面的內容很容易閱讀 -
char
在每場比賽之前放置不屬於比賽一部分的 a ,然後char
使用第二個s
命令刪除直到最後一個的所有內容 - 第二個
s
命令的另一個選項是刪除不屬於符合部分的字元之前的所有內容:
- 上面的內容很容易閱讀 -
<FILE sed -En '/([[:alpha:]]+-[0-9]+).*/{ s//\1/; s/.*[^[:alnum:]-]//; p; }'
答案3
我們Perl
可以這樣做:
$ perl -lne 'print /([a-z]+-\d+)/i' file
輸出:
HR-1
HR-2
HR-3
Cov-4