使用 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

相关内容