搜索和替换标签之间的字符串
Search and replace string between tags
我有以下 100,000 行的文档。在本文档中,我有一些不同语言的翻译,我的问题是我需要让“en_US”和“en”完全相同(标签之间的文本)。
我尝试使用 SED、AWK、TR,但我无法实现我的目标并且不影响其他语言。
有什么想法吗?
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage customer product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
期望的输出:
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
谢谢!
en_US总是在第一位吗?
import sys
state = 'bypass'
for line in open(sys.argv[1]):
line = line.rstrip()
if line.find("<tuv") >= 0 and line.find("en-US") >= 0:
state = 'grab'
elif line.find("<tuv") >= 0 and line.find("en") >= 0:
state = 'replace'
elif state == 'grab':
grab = line
state = 'bypass'
elif state == 'replace':
print(grab)
state = 'bypass'
continue
print(line)
如果这不仅仅是一次性的事情,我可能会考虑使用 XML 包来读取数据、转换数据并将其写回,但这对于一次性来说很好.
这是一个 awk 解决方案
$ cat tst.awk
BEGIN{
ins = "<seg>Enter and manage product details.</seg>" # Store text to insert in variable ins
}
/<tuv xml:lang="en(_US)?">/{f=1} # When regexp is found, f is set
f{ # With f true ...
if(/<\/tuv>/) f=0 # if end tag is found, unset f
else sub(/<seg.*$/, ins) # else substitute <seg> with ins text
}
{print}
$ awk -f tst.awk input
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
这可能适合您 (GNU sed):
sed -n '/"en_US"/{n;:a;N;/\n<\/tuv>/!ba;s/\n/\n/gp}' file |
sed '1{x;s/^/cat -/e;x}
/"en"/{n;:a;N;/\n<\/tuv>/!ba;g;s/\n.*//;s/\n/\n/g;x;s/[^\n]*\n//;x}' file
选择 en_US
之后的行并序列化(将 \n
替换为 \n
)直到下一个 <\tuv>
标记并将结果传递到标准输出。
在 sed 的第二次管道调用中,将上一次 sed 调用的结果存储在保留 space.
中
将 "en"
之后到标记 <\tuv>
的行替换为来自第一次调用的配对序列化行。
反序列化行并从保留中删除该行 space。
重复。
N.B。如果 "en_US"
总是在 "en"
之前并且 seg
标签只有一行,请使用:
sed '/"en_US"/{n;h};/"en"/{n;g}' file
我有以下 100,000 行的文档。在本文档中,我有一些不同语言的翻译,我的问题是我需要让“en_US”和“en”完全相同(标签之间的文本)。 我尝试使用 SED、AWK、TR,但我无法实现我的目标并且不影响其他语言。 有什么想法吗?
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage customer product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
期望的输出:
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
谢谢!
en_US总是在第一位吗?
import sys
state = 'bypass'
for line in open(sys.argv[1]):
line = line.rstrip()
if line.find("<tuv") >= 0 and line.find("en-US") >= 0:
state = 'grab'
elif line.find("<tuv") >= 0 and line.find("en") >= 0:
state = 'replace'
elif state == 'grab':
grab = line
state = 'bypass'
elif state == 'replace':
print(grab)
state = 'bypass'
continue
print(line)
如果这不仅仅是一次性的事情,我可能会考虑使用 XML 包来读取数据、转换数据并将其写回,但这对于一次性来说很好.
这是一个 awk 解决方案
$ cat tst.awk
BEGIN{
ins = "<seg>Enter and manage product details.</seg>" # Store text to insert in variable ins
}
/<tuv xml:lang="en(_US)?">/{f=1} # When regexp is found, f is set
f{ # With f true ...
if(/<\/tuv>/) f=0 # if end tag is found, unset f
else sub(/<seg.*$/, ins) # else substitute <seg> with ins text
}
{print}
$ awk -f tst.awk input
<prop type="context"></prop>
<tuv xml:lang="en_US">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="de">
<seg>Geben Sie die Produkt-Details ein und verwalten Sie diese.</seg>
</tuv>
<tuv xml:lang="en">
<seg>Enter and manage product details.</seg>
</tuv>
<tuv xml:lang="es">
<seg>Introduzca y gestione los detalles del producto.</seg>
</tuv>
<tuv xml:lang="fr_FR">
<seg>Entrez et gérez les détails sur le produit.</seg>
</tuv>
<tuv xml:lang="ja">
<seg>商品の詳細を入力、管理します。</seg>
</tuv>
<tuv xml:lang="zh_CN">
<seg>输入并管理产品详细信息。</seg>
</tuv>
这可能适合您 (GNU sed):
sed -n '/"en_US"/{n;:a;N;/\n<\/tuv>/!ba;s/\n/\n/gp}' file |
sed '1{x;s/^/cat -/e;x}
/"en"/{n;:a;N;/\n<\/tuv>/!ba;g;s/\n.*//;s/\n/\n/g;x;s/[^\n]*\n//;x}' file
选择 en_US
之后的行并序列化(将 \n
替换为 \n
)直到下一个 <\tuv>
标记并将结果传递到标准输出。
在 sed 的第二次管道调用中,将上一次 sed 调用的结果存储在保留 space.
中将 "en"
之后到标记 <\tuv>
的行替换为来自第一次调用的配对序列化行。
反序列化行并从保留中删除该行 space。
重复。
N.B。如果 "en_US"
总是在 "en"
之前并且 seg
标签只有一行,请使用:
sed '/"en_US"/{n;h};/"en"/{n;g}' file