Regex 在分隔符和正则表达式之间转换文本

Regex 在分隔符和正则表达式之间转换文本,regex,bash,macos,sed,Regex,Bash,Macos,Sed,我想将西里尔文字符转换为拉丁文字符,仅在特定分隔符-$$和[]之间转换。我在指定转换的范围时遇到问题 我想到了: sed -i '' '/[\[$][^$\[]*[\[$]/ y/АаІіВСсЕеРТтОоКкХхМ/AaIiBCcEePTtOoKkXxM/' wrong.txt 但这将替换以下示例中的所有文本: 错误的.txt: $ПRöVS$ $NUМ| Y$$DUСА|T S | Y$аааааааааааа “$АDJ$dhfg[Rööt.GаtNаmа]% $NАММ$\N” §Y

我想将西里尔文字符转换为拉丁文字符,仅在特定分隔符-
$$
[]
之间转换。我在指定转换的范围时遇到问题

我想到了:

sed -i '' '/[\[$][^$\[]*[\[$]/ y/АаІіВСсЕеРТтОоКкХхМ/AaIiBCcEePTtOoKkXxM/' wrong.txt
但这将替换以下示例中的所有文本:

错误的.txt:

$ПRöVS$
$NUМ| Y$$DUСА|T S | Y$аааааааааааа
“$АDJ$dhfg[Rööt.GаtNаmа]%
$NАММ$\N”
§Y$VАL$§!“
注意:我使用OSX

注2:转换不是问题,正则表达式是

预期输出(即指定标记内的文本变为拉丁语):

$证明$
$NUM | Y$$DUCATS | Y$баааааааааааа
“$ADJ$dhfg[Root.GetName]%
$NAME$\n“
§Y$VAL$§!“
[GetCapitalName]
使用sed进行这项工作(通常)会有点痛苦,Perl或awk解决方案可能会更短,可读性更好,但这里有一个在sed中使用的解决方案

它被称为

sed -E -f sedscr.sed wrong.txt
其中,
error.txt
是您的输入,sed脚本位于
sedscr.sed
中,如下所示:

/\$[^$]*\$/ {
    :label1
    h
    s/.*(\$[^$]*\$).*/\1/
    y/АаІіВСсЕеРТтОоКкХхМ/AaIiBCcEePTtOoKkXxM/
    s/\$/~~/g
    G
    s/(.*)\n(.*)\$[^$]*\$(.*)/\2\1\3/
    /\$[^$]*\$/b label1
    s/~~/$/g
}
/\[[^]]*\]/ {
    :label2
    h
    s/.*(\[[^]]*\]).*/\1/
    y/АаІіВСсЕеРТтОоКкХхМ/AaIiBCcEePTtOoKkXxM/
    s/[][]/~~/g
    G
    s/(.*)\n(.*)\[[^]]*\](.*)/\2\1\3/
    /\[[^]]*\]/b label2
    :label3
    s/~~/[/
    s/~~/]/
    /~~/b label3
}
两个主块分别检查该行是否包含
$$
[]
对,如果是,则进行翻译。模式总是一样的:假设你的线条看起来像

abcdef $abc$ abcdef $def$ abc
~~DEF~~
abcdef $abc$ abcdef $def$ abc
你想把它音译成大写。首先,我们将模式空间复制到保留空间(
h
),然后删除最后一对标记(
s/*(\$[^$]*\$)./\1/
)之外的所有内容。现在我们用
y/abcdef/abcdef/
音译

为了标记a对完成,我们将其替换为文本中没有的内容:两个
~
字符(
s/\$/~/g
G
将保留空间附加到模式空间,现在看起来像

abcdef $abc$ abcdef $def$ abc
~~DEF~~
abcdef $abc$ abcdef $def$ abc
复杂的替换
s/(.*)\n(.*)\$[^$]*\$(.*)/\2\1\3/
会导致

abcdef $abc$ abcdef ~~DEF~~ abc
现在,我们检查是否还有一对
$
,如果是,我们将分支到
:label1
/\$[^$]*\$/b label1
)。当我们不再进行分支时,所有的
$
都已处理完毕,我们可以再次将
~~
替换为
$
s/~/$/g

第二块中的
[]
原则上相同;唯一的区别是在替换
~
时,我们使用另一个循环,因为我们必须交替插入
[
]

这是输出:

$sed-E-f sedscr.sed-error.txt
挈挈挈挈挈挈挈挈挈挈挈挈挈$证明$
$NUM | Y$$DUCATS | Y$баааааааааааа
“$ADJ$dhfg[Root.GetName]%
$NAME$\n“
§Y$VAL$§!“
或者,更具说明性的是,在我的终端仿真器中显示非拉丁字符的前后:


看起来分隔的是拉丁字符,而不是西里尔字母。还有,这种转变正确吗?我的俄语非常生疏,但是
С
应该变成
S
,而
П
变成
R
,不?需要什么输出?根本问题是
y
在匹配的情况下作用于整行。地址只决定这一点,而不选择行的哪一部分。@BenjaminW。如果你想指定西里尔字母,这些字母是乌克兰字母。而且它们在视觉上看起来可能是一样的,你可以检查,它们实际上不是。你能添加预期的输出吗?谢谢,它起作用了。但如何抑制输出的打印?我尝试在
-E
之后添加
-n
,但它阻止了命令的执行。@AlCrow是否就地替换
sed-i'-E-f sedscr.sed-error.txt应该可以工作。