如何用同一文本行中的尾随字符替换字符匹配?

时间:2010-09-28 04:49:00

标签: linux bash ubuntu

我正在使用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。 ıo

输出文件格式

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

第一个输出行可能包含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

2 个答案:

答案 0 :(得分:0)

我觉得用sed或awk很难......

我建议使用Perl或Vim命令(如果你知道使用Vim):

vim命令是:

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

然后重复,直到完全停止后在行尾不再有元音。

\zs设置匹配开始,\ 1是后引用。*。把匹配的regexp放在括号内。

如果要处理所有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

答案 1 :(得分:0)

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

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

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

  

小学 - 我的电脑不工作A:¡没有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
}