我想知道是否可以使用sed
来匹配最长的字符串(从头开始)不包含子字符串,以后可以使用sed的正则表达式替换变量\n
来访问任何匹配。 / p>
关于以下代码段
echo "blabla/a/b/dee/per" | sed -r -e 's:([^/a]*):\1:g'
我正在尝试打印包含*
指示的任何符号的最长匹配,但不包括子串/a
以上述代码段打印出来的方式
blabla
关于(/a
删除/替换)
echo "blabla/b/b/dee/per" | sed -r -e 's:([^/a]*):\1:g'
我期待
blabla/b/b/dee/per
由于子串/a
导致的输出不可用,因此最长的匹配导致字符串结束。我被困在描述子串/a
。
注意: [^/a]
只是占位符来描述问题。它需要用正确的子字符串描述替换imo。
是否有可能以某种方式使用sed?
提前谢谢
编辑: John1024的第三个答案完成了这个问题。现在使用以下代码段:
sed -r -e 's:(/a|$):\x00:;s:^(.*)\x00(.*):\1:g'
编辑,以完成我的原始任务,将值添加到包含不同前缀的pathes中,其中包含由其他字符包围的子字符串,最后出现了
$ echo -ne "blabla/a/b/dee/per\nblabla/b/dee/per" | \
sed -r -e 's:(.*)/a/b:\1\x00:;s:(.*)/b:\1\x01:;s:^(.*)\x00(.*):\1/foo/a/b\2:g;s:^(.*)\x01(.*):\1/foo/b\2:g'
blabla/foo/a/b/dee/per
blabla/foo/b/dee/per
首先用/a/b
或/b
替换前缀pathes \x00
或\x01
,分别通过\n
访问sed组,即前缀和后缀pathes如下所述。
注:此处使用的其他技巧可避免(.*)/b
匹配(.*)/a/b
也就是首先替换最长的路径前缀。
再次感谢@ John1024
答案 0 :(得分:2)
/a
(问题的第二个版本)$ echo "blabla/a/b/dee/per" | sed 's|/a.*||'
blabla
$ echo "blabla/b/b/dee/per" | sed 's|/a.*||'
blabla/b/b/dee/per
/a
的最长字符串(原始问题)这个问题与awk更自然匹配:
$ echo "blabla/a/b/dee/per" | awk -v RS='/a' 'length($0)>max{longest=$0; max=length(longest);} END{print longest;}'
/b/dee/per
$ echo "blabla/b/b/dee/per" | awk -v RS='/a' 'length($0)>max{longest=$0; max=length(longest);} END{print longest;}'
blabla/b/b/dee/per
-v RS='/a'
这会将记录分隔符设置为/a
。这会在每次出现/a
。
length($0)>max{longest=$0; max=length(longest);}
如果当前记录$0
长于上一个最长记录,请使用新记录更新longest
和max
。
END{print longest;}
当我们到达输入的末尾时,打印出我们看到的longest
记录。
/a
开始捕获字符串(第3版问题)$ echo "blabla/a/b/dee/per" | sed -r 's!(/a|$)!\x00!; s|^(.*)\x00.*|I found "\1".|'
I found "blabla".
$ echo "blabla/b/b/dee/per" | sed -r 's!(/a|$)!\x00!; s|^(.*)\x00.*|I found "\1".|'
I found "blabla/b/b/dee/per".
工作原理:
s!(/a|$)!\x00!
这会将第一次出现的/a
替换为NUL字符\x00
。如果未找到/a
,则NUL字符将放置在字符串的末尾(由$
表示为正则表达式)。 (选择NUL字符是因为它永远不能保存在bash变量中,因此极不可能存在于输入字符串中。)
s|^(.*)\x00.*|I found "\1".|
这将第1组的所有字符保存到第一个/a
以前的位置。我们可以随意使用\1
。
如上所述,这需要一个sed,例如GNU sed,它支持NUL字符,十六进制00.如果你的sed不支持NUL,那么将\x00
替换为一些赢得' t在您的输入字符串中,但您的sed确实支持。 \x01
可能是一个不错的第二选择。