搜索和替换标签之间的字符串

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