如何使用 bash 替换获取字符串中的所有转义文字符号

如何使用 bash 替换获取字符串中的所有转义文字符号

我希望能够仅返回当前我正在执行的字符串中的转义文字:

foo="\'\"\(foobar\)'another'[program]\[\$var\]()"
echo "${foo//[^\\\']/}"

但它输出这个:

\'\\''\\

期望的输出应该是这样的:

\'\"\(\)\[\$\]

我仍然处于尝试获取文字单引号的阶段,但不知何故它不起作用,或者它在 bash 扩展中真的可行吗?

编辑

字符串来自 bash $READLINE_LINE,因此不会有像双引号的三重反斜杠那样的额外转义。

答案1

将变量设置为文字值

\'\"\(foobar\)'another'[program]\[\$var\]()

使用双引号字符串,您需要转义每个文字反斜杠每个双引号或美元符号否则会触发扩展。

string="\\'\\\"\\(foobar\\)'another'[program]\\[\\\$var\\]()"

如果使用单引号字符串,您只需关心特别插入单引号:

string='\'"'"'\"\(foobar\)'"'"'another'"'"'[program]\[\$var\]()'

在这里,我选择打破单引号字符串,为每个单引号添加双引号单引号,即'"'"'。您还可以在单​​引号字符串之外使用转义单引号,即'\''

如果引用变得太麻烦,您也可以选择使用引用的此处文档:

string=$( cat <<'END'
\'\"\(foobar\)'another'[program]\[\$var\]()
END
)

请注意,如果换行符是字符串中的最后一个字符,这将修剪掉尾随的换行符。

然后你的代码尝试删除所有反斜杠和单引号,这似乎不对。相反,使用一些工具提炼\和以下字符的所有实例:

grep -o '\\.' <<<"$string"

这会产生

\'
\"
\(
\)
\[
\$
\]

或者,

grep -o '\\.' <<<"$string" | paste -s -d '\0' -

准确地重现问题中的输出。

bash您也可以直接在循环中执行此操作:

while [[ $string =~ \\. ]]; do
    printf '%s\n' "${BASH_REMATCH[0]}"
    string=${string#*\\?}
done

或者,

while [[ $string =~ '\'. ]]; do
    printf '%s\n' "${BASH_REMATCH[0]}"
    string=${string#*'\'?}
done

string只要字符串中存在这样的字符序列,就会通过修剪直到反斜杠和其他字符的下一个匹配的位来修改 的值。在每次迭代中都会打印与给定正则表达式匹配的位。

答案2

使用zsh代替bash,你可以这样做:

set -o extendedglob
print -r -- ${foo//(#b)((\\?)|?)/$match[2]}

或者与ksh93

print -r -- "${foo//@(@(\\?)|@(?))/\2}"

(你认为print -r -- "${foo//@(@(\\?)|?)/\2}"也应该有效,但事实并非如此,看起来像一个错误

fish

string join '' (string match -ar '\\\\.' $foo)

答案3

我认为您不能使用模式替换操作来查找此类字符串,因为您需要查看前一个字符才能知道是否删除当前字符。你需要像 Perl 正则表达式的负向后查找之类的东西来做到这一点。如果你考虑像这样的字符串,那就更难了\\x,其中第一个反斜杠应该转义第二个反斜杠,但第二个反斜杠不应该转义x,至少在反斜杠转义通常起作用的范围内。

在循环中找到匹配的部分会更容易,但 Bash 也确实让这变得非常简单。 (有正则表达式匹配运算符[[ text =~ re ]],并且可以在 中找到匹配项${BASH_REMATCH[@]},但我认为除了手动之外,没有其他方法可以循环多次命中。)

但你可以用例如来做到这一点grep。例如,这将输出匹配序列,每行一个:

foo="\'\\\"\(foobar\)'another'[program]\[\$var\]()"
echo "$foo" | grep -oe '\\.'

然后通过管道输出以tr -d '\n'删除换行符。或者如果您需要在 shell 中处理它们,则使用while IFS= read -r line; do...,但如果您这样做,您可能应该使用其他工具; shell 不太适合文本处理。

相关内容