是否可以从 sed 内部传递对函数的反向引用?

问题描述

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 ...
'

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...