【问题标题】:How to substitue character matches with trailing characters from the same text line?如何用同一文本行中的尾随字符替换字符匹配?
【发布时间】:2010-09-28 04:48:59
【问题描述】:

我正在使用 pdftotext 转换西班牙语文本。带有重音符号或波浪号的字符以需要进一步转换的系统方式输出。重音符号和波浪线出现在转换后的文本中的正确位置,但没有字母。该字母几乎总是出现在输出行的末尾。如果没有,我可以手动修复它们。

例如pdf句子

¿Por qué?

变成

¿Por qu´? e

我对 sed、awk 和 grep 有足够的了解,我认为可以通过它们的某种组合来完成 - 而且这需要我很长时间。我打算用它来处理文件夹中的所有pdf文件。

这些句子以西班牙语-英语对出现在不同的行中。我想用分号分隔符将两者连接起来,这是我的闪存卡应用程序(Anki)的导入格式。删除所有非西英句对的内容。

例如,转换这个输出

B:

¿Por qu´? e
Why?

进入

¿Por qué?;Why?

如果有多个重音符号、波浪号或两者的混合,则行尾的字母顺序正确,并且可以用逗号分隔。比如pdf句子

Sí pero vi en la televisión que iba a llover.

变成

S´ pero vi en la televisi´n que iba a llover. ı, o

或 S´ pero vi en la televisi´n que iba a llover。我哦

输出文件格式

句子总是有一个结束标点符号,“!”,“?”或者 ”。”。对于那些不熟悉西班牙语的人来说,元音 (aeiou) 是唯一可能有重音的字母,字母“n”是唯一可能有波浪号的字母,两个特殊字符可以在大写和小写字母上找到.

第一个输出行可能包含 pdf 的级别和标题。级别和标题总是在“A:”的第一次出现之前

我对“关键词汇”这一行或任何后续行中出现的任何内容都不感兴趣。

pdftotext 以 UTF8 编码运行。我的操作系统是 Linux Mint 9,它基于 Ubuntu 10.04

以下是两个示例输出文件。

输出 1

Elementary - Credit Card A:

(B0089)

Me da la cuenta, por favor.
Bring me the check, please.

B:

Se la doy enseguida.
I’ll bring it to you right away.

B:

Perd´n se˜or, pero no aceptamos tarjeta. o n
Sorry sir, but we don’t take cards.

A:

¿No aceptan ninguna tarjeta de cr´dito? e
You don’t take any credit cards?


Key Vocabulary

tarjeta cr´dito e cuenta

Noun Noun Noun

card credit bill

输出 2

Elementary - My computer is not working A: ¡No puede ser!
It can’t be!

(B0079)

B:

¿Qu´ pasa? e
What happened?

A:

Mi computadora no est´ funcionando. a
My computer is not working.

B:

Rein´ ıciala.
Restart it.


Key Vocabulary

funcionar

Verb

to work

【问题讨论】:

    标签: linux bash ubuntu


    【解决方案1】:

    编辑:NR == 1 行稍作更改,以适应输入文件第一行的变化。为此,它取决于“A:”仅在第一行出现一次。

    我还应该补充一点,这个程序依赖于 GNU AWK (gawk) 的功能。

    您的两个输出示例之间似乎存在一些不一致之处。下面的程序适用于第一个程序。在第二个示例中,此行包含标题和数据行:

    初级 - 我的电脑不工作 A:¡No puede ser!

    并且此行包含要在该行内而不是在最后一个标点符号之后替换的字符。

    Rein´ ıciala。

    如果需要,可以通过修改程序来解决这些问题。

    另外,您提到这些字符将用逗号分隔,但示例没有它们(在它可能出现的一个地方)。没关系,因为我的程序忽略了逗号。

    您可以像这样运行以下程序:

    $ ./scriptname inputfile
    

    这就是它所有的笨拙:

    #!/usr/bin/awk -f
    BEGIN {
        FS = "[.?!]"
        chars["n"] = "˜ñ"
        chars["N"] = "˜Ñ"
        chars["a"] = "´á"
        chars["A"] = "´Á"
        chars["e"] = "´é"
        chars["E"] = "´É"
        chars["ı"] = "´í"
        chars["I"] = "´Í"
        chars["o"] = "´ó"
        chars["O"] = "´Ó"
        chars["u"] = "´ú"
        chars["U"] = "´Ú"
    }
    
    /Key Vocabulary/ {exit}
    
        NR == 1 { sub(".*A: *","",$1) }
    
        /^\(.*\) *$/ || \
        /^(A|B): *$/ || \
        /^ *$/ \
            {next}
    
    {
        punct = gensub($1"(.)"$2,"\\1","",$0)
    
        for (i=0; i<=length($2); i++) {
            char = substr($2,i,1);
            if (char != " ") {
                sub(substr(chars[char],1,1),substr(chars[char],2,1),$1)
            }
        }
    
        printf "%s%s;", $1, punct
        getline
        print
    }
    

    【讨论】:

    • “你的两个输出示例之间的不一致”是故意的,都是有效的输出。我试图在我的问题中通过说“第一个输出行可能包含 pdf 的级别和标题。级别和标题总是在“A:”的第一次出现之前来解释这一点
    • 感谢您指出我的示例与问题不匹配的地方。我已经更新了问题。
    • @Bill:我做了一个小改动,应该能够处理第一行包含一行数据的情况。
    【解决方案2】:

    我认为使用 sed 或 awk 会很困难……

    我建议使用 Perl 或 Vim 命令来执行此操作(如果您知道使用 Vim):

    vim 命令是:

    :%s/^.\{-}\zs´\(.*\.\) ı\(,\|$\)/í\1/
    :%s/^.\{-}\zs´\(.*\.\) o\(,\|$\)/ó\1/
    :%s/^.\{-}\zs´\(.*\.\) e\(,\|$\)/é\1/
    : " etc
    

    然后重复,直到句号后的行尾不再有元音。

    \zs 设置匹配开始,\1 是对 .* 的反向引用。在匹配的正则表达式中放入括号。

    如果要处理所有pdf文件,请执行以下操作:

    vim *.pdf
    :set hidden   "allows modifying a not-on-display buffer
    :bufdo %s/^.\{-}\zs´\(.*\.\) ı\(,\|$\)/í\1/
    :bufdo %s/^.\{-}\zs´\(.*\.\) o\(,\|$\)/ó\1/
    : " etc
    :next         "allows you to see other buffers to validate
    :bufdo w      "will save all buffers
    :q            "will quit
    

    【讨论】:

    • 我对 vim 的了解接近于零,所以无法测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    相关资源
    最近更新 更多