簡體   English   中英

SED:同一行上的多個模式,如何匹配/解析第一個

[英]SED: multiple patterns on the same line, how to match/parse first one

我有一個文件,里面有電話號碼數據,還有一些沒用的東西。 我正在嘗試解析數字,當只有 1 個電話號碼/線路時,這不是問題。 但是當我有多個數字時,sed 匹配最后一個(即使它到處都說它應該只匹配第一個模式?),我無法得到其他數字。

我的數據.txt:

bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla

當我解析數據時,我的想法是首先刪除第一個電話號碼前面的所有“初始”“bla bla bla”(因此我搜索第一次出現的 'NUM:'),然后刪除所有內容在電話號碼之后,並獲取號碼。 之后,我想從剩余的字符串中解析下一次出現。

所以現在當我嘗試 sed 時,我總是得到最后一個數字:

>sed 's/.*NUM://' data.txt
08022222222 bla bla bla
> 

主要是我想了解我對 SED 的理解有什么問題。 當然歡迎更有效的建議! 我的 sed 命令不是說,用 ''(空)替換 'NUM:' 之前的所有內容嗎? 為什么它總是匹配最后一次出現?

謝謝!

這可能對你有用:

echo "bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla" |
sed 's/NUM:/\n&/g;s/[^\n]*\n\(NUM:[0-9]*\)[^\n]*/\1 /g;s/.$//'
NUM:09011111111 NUM:08022222222

您遇到的問題是理解.*是貪婪的,即它匹配最長的匹配而不是第一個匹配。 通過在我們感興趣的字符串( NUM:... )前面放置一個唯一字符( \\n sed 將其用作行分隔符,因此它不能存在於行中)並刪除所有不是該唯一字符的內容[^\\n]*后跟唯一字符\\n ,我們有效地將字符串拆分為可管理的部分。

正如您現在所知, sed表達式是貪婪的,據我所知不能成為非貪婪的。

到目前為止尚未提出的兩種替代方案是僅使用其他工具進行此類匹配/提取。

您可以使用perl作為帶有-pe參數的 sed 的替代品。 它支持? 非貪婪修飾符:

$ perl -pe 's/.*?NUM://' data.txt
09011111111 bla bla bla bla NUM:08022222222 bla bla bla

您可以使用 GNU grep 的-o選項來僅獲取與正則表達式匹配的數據位:

$ egrep -o 'NUM:[0-9]*' data.txt 
NUM:09011111111
NUM:08022222222

如果數字由NUM:后面的NUM:定義:

sed -n -e 's/$/\n/' -e ':begin' \
  -e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
  -e 'tbegin' -e 's/.*\n //' -e '/NUM/p'

它的作用是:

  1. 在行尾放置一個\\n作為標記。
  2. 嘗試在標記之前找到一個數字,並將其放在行尾(標記之后)。
  3. 如果找到一個數字,請轉到上面的 2。
  4. 當標記前沒有數字時,刪除數字前的所有內容。
  5. 如果一行中有數字,則打印它(以處理找不到數字的情況。

也可以反過來做,首先刪除沒有數字的行:

sed  -e '/NUM/!d' -e 's/$/\n/' -e ':begin' \
  -e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
  -e 'tbegin' -e 's/.*\n //'
sed -E 's/(-y)|(-f)|(\+incdir\+)/\n&/g' abcfile > cdeop

其中 abcfile 將作為示例 -y / -f / +incdir+ patterns ,當模式匹配時,它將在其之前插入新行。

您可以使用此模式:

sed -r 's/^(.*NUM:)(.*NUM:.*)$/\2/'

暫無
暫無

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

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