使用 sed 提取在第一次出現結尾處停止的子字串

使用 sed 提取在第一次出現結尾處停止的子字串

我有一個字串,需要從中提取子字串,但正規表示式的末尾是重複的。我希望 sed 在正規表示式末尾的第一個實例處停止,就像許多語言中的 instr() 函數會傳回第一個實例一樣。例子:

echo "This is a test some stuff I want string junk string end" | sed -n 's/.*\(.te.*ng\).*/\1/p' 
returns: test some stuff I want string junk string
I want to return: test some stuff I want string

答案1

grep方法(需要聚合酶鍊式反應支持):

s="This is a test some stuff I want string junk string end"
grep -Po 'te.*?ng' <<< $s

選擇珀爾方法:

perl -ne 'print "$&\n" if /te.*?ng/' <<< $s

輸出(兩種方法):

test some stuff I want string

  • .*?-?這是非貪婪修飾符,告訴匹配極簡時尚

答案2

分兩步驟進行:先刪除前綴(如果前綴中存在終止符),然後刪除前綴後面的所有內容。如果不匹配,使用T命令跳過一行:

echo "This is a test some stuff I want string junk string end" |
sed -n 's/.*\(.te.*ng\)/\1/; T; s/\(ng\).*/\1/p'

或者,先刪除不符合的行,然後隨意執行替換。

echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/!d; s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/'

或者,僅在匹配的行上執行替換和最終列印。

echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/ { s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/p; }'

答案3

我建議在你的情況下使用 cut 指令

echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1

這會將字串切割成三部分(第一部分之前,第二部分之後。以及「字串」之間),使用-d"" 您可以選擇要用作切割器的模式,使用-fNumber 您可以選擇要使用的部分拿。問題:「字串」將被刪除解決方案:

String=`echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1`
String="$(String) string"
echo $String

它將刪除的分隔符號「字串」新增到使用輸出定義的 $String 變數的末尾

答案4

# 如何使用 POSIX sed 執行貪婪匹配:“test .*? string”

sed -e '
   /test.*string/!d;      # non-interesting line
   /^test/s/string/&\
/;                        # append marker after the first substring "string"
   /\n/{P;d;}             # initial portion of pattern space is our result
   s/test/\
&/;D;                     # remove portion before the substring "test"
' yourfile

其他POSIX-方法是從模式空間的末尾取出子字串“string”,一次1個,直到只剩下一個(在子字串“test”之後)。然後剩下的就是將子字串“test”放在前面:

sed -e '
   :loop
      s/\(test.*string\).*string.*/\1/
   tloop
   /^test/!s/test/\
&/;/\n/D
' yourfile

相關內容