【问题标题】:Escaping double quotation marks in sed在 sed 中转义双引号
【发布时间】:2017-09-13 12:05:34
【问题描述】:

为我的应用程序创建搜索和替换功能,我正在运行一个包含 3 个文件的测试场景, 大批 脚本 测试

我正在尝试转义双引号,但它不起作用

脚本文件包含

variableName=$1
sed "s#data\-field\=\"${variableName}\.name\"#data\-field\=${variableName}\.name data\-type\=dropdown data\-dropdown\-type\=${variableName}#g" test

测试文件包含

data-field=“fee_category.name”
data-field=“tax_type.name”

数组文件包含

fee_category
tax_type

没有错误代码,输出就是我输入的内容,因为 sed 命令找不到它要查找的内容,如果我不在 ${VariableName} 旁边使用双引号并将它们从测试文件中删除工作正常。

【问题讨论】:

  • 您的示例输入包含non-ASCII double quotes,而sed 命令与" 不匹配。
  • 您要搜索文字字符串还是正则表达式?如果它是正则表达式,您是否要启用捕获组?是否要在替换文本中启用反向引用元字符(例如 &\1)?
  • 我正在搜索文字字符串并使用正则表达式替换它
  • 也许我没有说清楚。如果variableName 的值为foo.bar,您是要搜索文字字符串foo.bar 还是要搜索正则表达式foo<any character>bar,例如,前者将不匹配foo8bar 而后者会匹配吗?
  • sed 中的双引号通常不需要转义。如果这些字符不是 ascii 双引号(十六进制 022),我们需要确定它们是什么。 head -n2 testfile | od -t x1c 的输出是什么?

标签: regex bash shell sed


【解决方案1】:

根据mklement0 的评论,我写这个答案只是为了分享我的一些发现,以防我们需要您的特殊双引号的文字匹配。它可能对其他用户有用。

您引用的文本fee_category.name 在左侧有Unicode Left Double Quotation Mark U+201c 引号,在右侧有Unicode Right Double Quotation Mark U+201d

那些非标准引号在 UTF-8 中也有一些表示:

Unicode Left Double Quotation Mark U+201c
UTF-8(十六进制)0xE2 0x80 0x9C (e2809c)
UTF-16 (十六进制) 0x201C (201c)

Unicode Right Double Quotation Mark U+201d
UTF-8(十六进制)0xE2 0x80 0x9D (e2809d)
UTF-16(十六进制)0x201D(201d)

使用od 实用程序分析您的文件,我们可以确认您的数据中是否存在上述 hex utf-8 序列:

$ echo data-field=“fee_category.name” |od -w40 -t x1c
0000000  64  61  74  61  2d  66  69  65  6c  64  3d  e2  80  9c  66  65  65  5f  63  61  74  65  67  6f  72  79  2e  6e  61  6d  65  e2  80  9d  0a
          d   a   t   a   -   f   i   e   l   d   = 342 200 234   f   e   e   _   c   a   t   e   g   o   r   y   .   n   a   m   e 342 200 235  \n

有趣的是,我们可以通过使用它们的 unicode 代码或使用 utf-8 hex 系列在 bash 中打印这些 un​​icode 字符:

$ echo -e "\u201c test \u201d"
“ test ”
$ echo -e "\xe2\x80\x9c test \xe2\x80\x9d"
“ test ”

因此,我们可以强制 sed 像这样匹配那些特殊字符:

$ string=$(echo -e "\u201c test \u201d");echo "$string"
“ test ”
$ lq=$(echo -ne "\u201c");rq=$(echo -ne "\u201d")
$ sed -E "s/($lq)(.+)($rq)/**\2**/" <<<"$string"
** test **

这似乎也可以正常工作,无需使用“辅助”变量:

$ sed -E "s/(\xe2\x80\x9c)(.+)(\xe2\x80\x9d)/**\2**/" <<<"$string"
** test **

这意味着sed 可以直接使用十六进制序列\xe2\x80\x9c(或\xe2\x80\x9d 用于右引号)在此特殊引号上提供文字匹配。

您不妨对文件进行预处理,并使用以下方式将所有非标准引号转换为标准引号:

$ sed -E "s/[\xe2\x80\x9c,\xe2\x80\x9d]/\x22/g" <<<"$string"
" test "   #Special quotes replaced with classic ascii quotes.

上述测试已在 Debian 测试和 Bash 4.4 和 GNU Sed 4.4 中完成,并且可能这种技术不适用于其他 sed 风格。

【讨论】:

    【解决方案2】:

    如有疑问,您可以尝试使用通配符:

    variableName="fee_category"
    sed "s#data-field=.${variableName}\.name.#& data-type=dropdown data-dropdown-type=${variableName}#g" test
    
    # Or, when you do not want those quotes back in your output
    sed "s#\(data-field=\).\(${variableName}\)\(\.name\).#\1\2\3 data-type=dropdown data-dropdown-type=\2#g" test
    

    【讨论】:

      猜你喜欢
      • 2015-11-06
      • 2020-06-08
      • 2011-11-22
      • 2011-11-17
      • 2014-03-20
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2013-02-24
      相关资源
      最近更新 更多