问题描述
TL;DR 这是不可能的,因为“在运行 sed 之前,命令替换中的反向引用不是也不会由 sed 解析,而是由 shell 解析”(请参阅下面的答案)。
我想用大文本文件 (>50MB) 中的相应字符替换国际音标的 unicode 值。
我的 test.txt 输入示例:
<CHARSET c="T">02C8;</CHARSET>ku:p<CHARSET c="T">0252;</CHARSET>n] noun<BR>
预期结果:
<CHARSET c="T">ˈ</CHARSET>ku:p<CHARSET c="T">ɒ</CHARSET>n] noun<BR>
我可以使用此命令(例如)转换给定的 unicode:
echo -e "\u02C8"
但是我在 sed 命令中转义失败了。我想到从 here 创建一个函数,如下所示:
codetochar() { $( echo -e "\u$1"); }
sed -r -i 's#(<CHARSET c="T">)(....)#\1'"$(codetochar \\2)"'#g' test.txt
但似乎“\2”反向引用没有传递给函数:
codetochar() { $( echo -e "\u$1"); }
sed -r -i 's#(<CHARSET c="T">)(....)#\1'"$(codetochar \\2)"'#g' test.txt
++ codetochar '\2'
+++ echo -e '\u\2'
++ '\u\2'
./replace.sh: line 2: \u\2: command not found
+ sed -r -i 's#(<CHARSET c="T">)(....)#\1#g' test.tx
解决方法
如何正确转义 sed 中的反向引用以将其传递给函数?
呈现的代码正确处理反向引用。在运行 sed
之前,命令替换中的反向引用不会也不会由 sed
解析,而是由 shell 解析。程序的参数必须在运行程序之前展开。
您可能会对 sed
使用 GNU 扩展 - e
标志为 s
命令,该命令通过 /bin/sh
解释执行替换模式。非常不鼓励使用此标志,并且很难使用,因为确定正确的引用和转义非常困难 - 它在非常简单的情况下“有效”。因为输入字符串有 ;
<
>
和 "
特殊 shell 字符,我怀疑这是可能的。
我建议选择一种成熟的编程语言,例如 python、perl 或其他语言来解决您的任务。 sed
不是根据文件内容动态执行操作的实用程序,它是一个简单的流替换实用程序。
在 sed
中,可以构建一个静态字符串列表来替换,如下所示:
sed -r '
s/(<CHARSET c="T">)02C8/\1'"$(echo -e "\u02C8")"/
s/(<CHARSET c="T">)0252/\1'"$(echo -e "\u0252")"/
.... one s/// command for each character to replace ...
'