我有包含转义和未转义正斜杠的字符串。
我正在寻找 sed 替代品来逃避只有未转义的斜杠,但似乎不支持负向后查找。
例子:
input: "https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https://baz/test.com"
desired output: "https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https:\/\/baz\/test.com"
答案1
sed
用途POSIX 基本正则表达式默认情况下,它不包括通常在 Perl 兼容的正则表达式语言中找到的先行断言和其他零宽度断言。
相反,只需取消转义转义的斜杠,然后转义修改后的字符串中的所有斜杠:
sed -e 's@\\/@/@g' -e 's@/@\\/@g'
这首先将所有实例更改为\/
,/
然后全部/
更改为\/
。这@
是替换命令的替代分隔符,以避免牙签倾斜综合症(您几乎可以使用任何其他字符)。
例子:
$ echo '"https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https://baz/test.com"' | sed -e 's@\\/@/@g' -e 's@/@\\/@g'
"https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https:\/\/baz\/test.com"
如果文本行存储在 shell 中的字符串中bash
,您可以在那里执行类似的操作:
$ string='"https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https://baz/test.com"'
$ string=${string//\\\///} # leaning toothpick warning!
$ string=${string//\//\\/}
$ printf '%s\n' "$string"
"https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https:\/\/baz\/test.com"
上面使用变量替换将in${variable//pattern/replacement}
的所有匹配项替换为。pattern
$variable
replacement
答案2
在 Perl 中,你可以使用lookbehinds:
$ input="https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https://baz/test.com"
$ printf '%s\n' "$input" | perl -pe 's|(?<!\\)/|\\/|g'
https:\/\/github.com\/foo\/bar\/pull\/2934) is live at https:\/\/baz\/test.com
答案3
这应该可以解决问题
sed 's:\\\?/:\\/:g'
将任何带有零个或前面一个反斜杠的斜杠替换为转义斜杠。
答案4
sed 没有后向断言,但我们可以模拟它们。此处显示的是扩展正则表达式模式下的 GNU sed (-E)
sed -E '
:a
s:(^|[^\])(([\][\])*)[/]:\1\2\\/:
t a
' file
在看到非反斜杠或到达行首之前,我们确保 / 左侧有偶数个反斜杠(0 是偶数)。