我有一个字符串,需要从中提取子字符串,但正则表达式的末尾是重复的。我希望 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