繁体   English   中英

BASH在单引号内转义双引号

[英]BASH escaping double quotes within single quotes

我正在尝试编写一个bash函数,该函数将转义单引号内的所有双引号,例如:

'I need to escape "these" quotes with backslashes'

会成为

'I need to escape \"these\" quotes with backslashes'

我的看法是:

  1. 在输入中查找单引号对,并使用grep提取它们
  2. 插入sed,转义双引号
  3. 再次对整个输入进行sed,并用sedded match替换grep match

我设法使它在正确地转义了引号部分的部分起作用,但是在整个输入中替换它失败。

脚本代码copypaste:

# $1 - Full name, $2 - minified name
adjust_quotes ()
{
    SINGLE_QUOTES=`grep -Eo "'.*'" $2`
    ESCAPED_QUOTES=`echo $SINGLE_QUOTES | sed 's|"|\\\\"|g'`
    sed -r "s|'.*'|$ESCAPED_QUOTES|g" "$2" > "$2.escaped"
    mv "$2.escaped" $2
    echo "Quotes escaped within single quotes on $2"
}

随机附加问题:

  • 在控制台中,仅用两个反斜杠将引号转义是可行的,但是在脚本中放置代码时-我需要四个。 我很想知道
  • 我可以将此代码修改为一个循环,以逐个转义所有单引号对,直到EOF为止吗?

谢谢!

PS我知道这可能会更容易做到,例如。 python,但我确实需要将其保留在bash中。

使用BASH字符串替换:

s='I need to escape "these" quotes with backslashes'
r="${s//\"/\\\"}"
echo "$r"
I need to escape \"these\" quotes with backslashes

这是一个纯bash解决方案,它可以在stdin上进行转换,并打印到stdout。 它会将整个输入读取到内存中,因此无法处理非常大的文件。

escape_enclosed_quotes() (
  IFS=\'
  read -d '' -r -a fields
  for ((i=1; i<${#fields[@]}; i+=2)); do
    fields[i]=${fields[i]//\"/\\\"}
  done
  printf %s "${fields[*]}"
)

我故意将函数的主体括在括号中,而不是用大括号括起来,以强制主体在子外壳中运行。 这就限制了IFS对主体的修改,以及隐式地使使用的变量成为局部变量。

该函数使用read内置函数将整个输入(由于使用-d ''将行定界符设置为NUL)读取到数组( -a )中,并使用单引号作为字段分隔符( IFS=\\' )。 结果是用单引号括起来的输入部分位于数组的奇数位置,因此该函数在奇数索引上循环以仅对那些字段进行替换。 我使用bash的查找和替换语法,而不是使用sed这样的外部实用程序。

这是重击,有一些陷阱:

  1. 如果文件包含NUL,则文件的其余部分将被忽略。
  2. 如果文件的最后一行不以换行符结尾,并且该行的最后一个字符是单引号,则将不会输出。

在便携式文本文件中不可能同时满足以上两个条件,因此可能没问题。 都一样,值得注意。


补充问题:为什么在代码中需要额外的反斜杠

ESCAPED_QUOTES=`echo $SINGLE_QUOTES | sed 's|"|\\\\"|g'`

答:与脚本中的这一行无关。 它与您使用反引号( ... )进行命令替换以及反引号内部的反斜杠的特殊且通常不可预测的处理有关。 不建议使用此语法。 不要使用它。 (即使在Internet上的一些随机示例中,即使您看到有人使用它也没有。)如果您使用推荐的$(...)语法进行命令替换,则该语法将按预期工作:

ESCAPED_QUOTES=$(echo $SINGLE_QUOTES | sed 's|"|\\"|g')

(更多信息在上面链接的Bash FAQ中 。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM