如何替换 sed 中的可选后缀

如何替换 sed 中的可选后缀

我使用 2 行(带和不带可选后缀)进行测试(最后 2 个枚举元素,D2,E2)。

echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | sed -E 's/^(.*),(.*),(.*)((,.*)(,.*)){0,1}$/[\1],\2,\3\5\6/'

[A1],B2,C2
[A2,B2,C2],D2,E2

我想从哪里获得

[A1],B2,C2
[A2],B2,C2,D2,E2

我只想将最后两个组件设为可选,并将它们附加在末尾以防找到它们。

我尝试使用重复 {x,y} 和问号 (?),但我无法使 sed find 模式上的最后 2 个元素真正成为可选。看起来 sed 贪婪非常贪婪,因为我用 '^' 和 '$' 包装模式,而不是首先尝试不可选的模式,它只采用具有非常贪婪的第一个组件的可选模式。

注意:正则表达式是我真正需求的简化,因此通过不同的方法克服可能是徒劳的。我真的很想用 sed 和这种特殊的方法来做到这一点,因为这只是为了提高我对该工具技巧的了解

编辑:感谢您的回答,这是我的目标

sed -E 's/^([^,]*),([^,]*),([^,]*)(,[^,]*)?(,[^,]*)?$/[\1],\2,\3\4\5/'

答案1

我不确定你的 sed 构造的目的,但我可以告诉你你的错误。
在正则表达式中,您尝试将前三个字母数字组合与(.*),(.*),(.*).由于 sed 中的正则表达式是“贪婪的”,第一个(.*)已经匹配三个组合,因为字母、数字和逗号与..要匹配单个组合,您最好匹配无逗号的字符(例如 ([^,]*),witch 匹配任意数量的无逗号字符。您的命令将如下所示:

echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | sed -E 's/^([^,]*),([^,]*),([^,]*)((,[^,]*)(,[^,]*)){0,1}$/[\1],\2,\3\5\6/'

如果它始终是三个或五个组合输入,您还可以将正则表达式“缩短”为

echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | sed -E 's/^([^,]*)(((,[^,]*){2}){1,2})$/[\1]\2/'

但这实际上取决于您的用例。
匹配^([^,]*)第一个字母数字组合,
匹配((,[^,]*){2})接下来的两个或四个组合,前面有一个逗号(输入示例中的,B2,C2 或,B2,C2,D2,E2)。

答案2

仍然不确定 OP 想要实现什么,但要进行非贪婪匹配,您可以使用否定字符类,在本例中为[^,]

echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | 
    sed -E 's/([^,]+)((,[^,]+){2})((,[^,]+){0,2})/[\1]\2\4/'

[A1],B2,C2
[A2],B2,C2,D2,E2

echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | 
    sed -E 's/([^,]+)((,[^,]+){2})((,[^,]+){0,2})/[\1]\2\5/'

[A1],B2,C2
[A2],B2,C2,E2

虽然分别捕捉每场比赛是另一回事...

如果OP愿意给出一个更完整的例子......也许我们都可以再次循环!这项练习对我们有好处;)

答案3

$ echo -e "A1,B2,C2\nA2,B2,C2,D2,E2" | sed -e 's/[^,]*/[&]/' -e 's/[^,]*/(&)/2' -e 's/[^,]*/{&}/3'
[A1],(B2),{C2}
[A2],(B2),{C2},D2,E2

您不必尝试在一次替换中完成所有操作,而是可以利用这样一个事实:您可以通过在末尾使用数字标志来选择要处理的一场比赛(此处/2以及/3第二场和第三场比赛)。

为了清楚起见,上面使用的命令sed

sed -e 's/[^,]*/[&]/' \
    -e 's/[^,]*/(&)/2' \
    -e 's/[^,]*/{&}/3'

相关内容