使用sed进行替换我希望匹配第一个字符,从左到右,以及匹配的所有内容。以下不起作用。
echo "a_4_3_2_1" | sed 's/.*\(_.*\)/\1/'
和
echo "a_3_2_1" | sed 's/.*\(_.*\)/\1/'
两者仅输出_1
我希望输出为:_4_3_2_1
和_3_2_1
如何编写sed替换以从左到右匹配并捕获匹配的所有内容?
答案 0 :(得分:4)
例如:
echo "a_4_3_2_1" | sed 's/[^_]*\(_.*\)/\1/'
或
echo "a_4_3_2_1" | sed 's/[^_]*//'
或
echo "a_4_3_2_1" | grep -oP '^[^_]*\K.*'
在bash UUOE中 - 无用的回声。最好写:
grep -oP '^[^_]*\K.*' <<<"a_4_3_2_1"
完全跳过第一个字符:
grep -oP '^.\K.*' <<< "a_4_3_2_1"
或
sed 's/.//' <<< "a_4_3_2_1"
纯bash
s="a_4_3_2_1"
echo "${s:1}"
答案 1 :(得分:2)
好消息是你的替换已被写入&#34;从左到右匹配并捕获匹配的所有内容&#34;!但是有两件事要记住你当前的代码无效。
首先,您在括号中的组之前所要求的匹配是.*
。 .
匹配任何字符,*
匹配零次或多次匹配。因此代码匹配任何字符的零次或多次出现。但有多少次出现是零或多?
受第二件事的影响。默认情况下,匹配是贪婪的:它们匹配尽可能多的字符而不会导致匹配失败。在这种情况下,他们可以匹配最后一个下划线(最后一个1
之前的那个)。
您可以修复您的模式以匹配单个字符:.
而不是*
:
echo "a_4_3_2_1" | sed 's/.\(_.*\)/\1/'
_4_3_2_1
某些工具允许使用minimal match,这会使匹配变得非贪婪。但不是sed
。
答案 2 :(得分:1)
sed regexes&#34; greedy&#34;意味着他们总是匹配最长的匹配。因此,您的示例会失败,因为第一个.*
会在_.*
匹配它们之前占用所有下划线。