sed:刪除字串之間的文本,直到第一次出現另一個字串

sed:刪除字串之間的文本,直到第一次出現另一個字串

想像我有類似以下文字的內容:

2012年和2013年,敏捷的棕色狐狸跳躍

我希望刪除“fox”中的部分,包括四個數字,但僅在第一次出現時刪除,所以我最終得到:

快棕色和 2013

有這樣的東西...:

echo「2012年和2013年快速的棕色狐狸跳躍」\
   | sed "s/fox.*\([0-9]\{4\}\)//g"

....帶給我:

快速棕色

因此它刪除了所有內容,包括最後一次出現的四個數字。

有任何想法嗎?

答案1

(「基本」和「擴展」版本)使用的 POSIX 正規表示式sed不支援非貪婪匹配。 (儘管有一些解決方法,例如使用[^0-9]*代替.*,但如果輸入變化很大,它們就會變得不可靠。)

?您可以透過使用非貪婪量詞在 Perl 中實現您所需要的:

echo "The quick brown fox jumps in 2012 and 2013" \
   | perl -pe 's/fox.*?([0-9]{4})//g'

您可能還想刪除多餘的空格。

答案2

假設你想使用僅有的sed 並且您希望匹配的結尾是第一組數字,而不關心數字後面的單字是什麼,這是有效的:

echo「2012年和2013年快速的棕色狐狸跳躍」\
   | sed "s/fox[^0-9][^0-9]*[0-9][0-9]* //"

此模式的工作原理是先匹配fox,後面接著一個或多個非數字[^0-9][^0-9]*,然後再跟 1 個或多個數字[0-9][0-9]*。此模式適用於任意數量的數字,而不僅僅是 4 個數字。

echo「2012年和2013年快速的棕色狐狸跳躍」\
   | sed "s/fox[^0-9]*\([0-9]\{4\}\) //"

答案3

你沒有指定確切地你的要求是什麼。您可能需要一個多步驟的過程。選擇一個您知道不會出現在輸入中的字串(例如####):

echo “2012 年和 2013 年,敏捷的棕色狐狸跳過了 42 隻懶狗。” \
  | sed\
        -e "s/[0-9]\{4\}/&####/" \
        -e "s/fox.*####//" \
        -e“s/####//”

(為了方便閱讀,命令被過度折疊。)之後-e "s/[0-9]\{4\}/&####/"注入####首先四位數。 (警告:這將更改為655366553####6
-e "s/fox.*####//"影響包含fox和的行####——即包含至少一個四位數字的行——然後從 到fox刪除首先四位數。
-e "s/####//"當然,會清除####包含四位數字但不包含 的行中剩餘的任何字串fox

如果有的話,還要刪除數字後面的一個空格,

echo “2012 年和 2013 年,敏捷的棕色狐狸跳過了 42 隻懶狗。” \
  | sed\
        -e "s/[0-9]\{4\}/&####/" \
        -e "s/fox.*#### //" \
        -e "s/fox.*####//" \
        -e“s/####//”

警告:您可以添加g到所有s命令,但是,由於這仍然使用.*,這是問題的根源,它仍然無法處理

One fox jumps in 2012 and 2013, another fox will jump in 2014 and 2015.

你可能想要的方式。當然,還有你想要添加g到,"s/[0-9]\{4\}/&####/"因為它會在之後####注入每一個四位數,打敗整點。然後,"s/fox.*####//"最終的行為就像"s/fox.*[0-9]\{4\}//"(您的原始命令已刪除非貢獻字元);即,它會改變

棕色狐狸在 2012 年和 2013 年跳躍得很快。

敏捷的棕色狐狸在 2012 年#### 和 2013 年#### 跳躍。

然後到

快棕色。

相關內容