我有一个sed(1)
脚本执行给定的许多逐步转换(替换)
输入流,适用于任务本身。现在,我需要的是限制这些
操作/内部“/”仅引用多行字符串。输入流是简单文本
包含多行“/”引用字符串的文件我需要执行我的
s///
命令的序列。我知道在sed(1)
中实现这一点很难
我仍然希望有人知道如何。我到目前为止的脚本(但在单行基础上正常工作)如下。
sed(1)
“诡计”在开头和时候
脚本的结尾,其余的只是s///
s表达式的序列,它是正确的:
#! /bin/sed -f
# Convert /PinYin/ strings to /UTF-8 PinYin/ strings.
# Notice: /PinYin/ strings MUST NOT be multiline (to do).
/\/.*\// {
s/\//\
/g
:a
h
s/[^\n]*\n//
s/\n.*//
s/ang1/||aq||ng/g
s/ang2/||aw||ng/g
s/ang3/||ae||ng/g
s/ang4/||ar||ng/g
s/eng1/||eq||ng/g
s/eng2/||ew||ng/g
s/eng3/||ee||ng/g
s/eng4/||er||ng/g
s/ing1/||iq||ng/g
s/ing2/||iw||ng/g
s/ing3/||ie||ng/g
s/ing4/||ir||ng/g
s/ong1/||oq||ng/g
s/ong2/||ow||ng/g
s/ong3/||oe||ng/g
s/ong4/||or||ng/g
s/an1/||aq||n/g
s/an2/||aw||n/g
s/an3/||ae||n/g
s/an4/||ar||n/g
s/en1/||eq||n/g
s/en2/||ew||n/g
s/en3/||ee||n/g
s/en4/||er||n/g
s/in1/||iq||n/g
s/in2/||iw||n/g
s/in3/||ie||n/g
s/in4/||ir||n/g
s/un1/||uq||n/g
s/un2/||uw||n/g
s/un3/||ue||n/g
s/un4/||ur||n/g
s/ao1/||aq||o/g
s/ao2/||aw||o/g
s/ao3/||ae||o/g
s/ao4/||ar||o/g
s/ou1/||oq||u/g
s/ou2/||ow||u/g
s/ou3/||oe||u/g
s/ou4/||or||u/g
s/ai1/||aq||i/g
s/ai2/||aw||i/g
s/ai3/||ae||i/g
s/ai4/||ar||i/g
s/ei1/||eq||i/g
s/ei2/||ew||i/g
s/ei3/||ee||i/g
s/ei4/||er||i/g
s/a1/||aq||/g
s/a2/||aw||/g
s/a3/||ae||/g
s/a4/||ar||/g
s/a1/||aq||/g
s/a2/||aw||/g
s/a3/||ae||/g
s/a4/||ar||/g
s/er2/||ew||r/g
s/er3/||ee||r/g
s/er4/||er||r/g
s/lyue/l||u:||e/g
s/nyue/n||u:||e/g
s/e1/||eq||/g
s/e2/||ew||/g
s/e3/||ee||/g
s/e4/||er||/g
s/o1/||oq||/g
s/o2/||ow||/g
s/o3/||oe||/g
s/o4/||or||/g
s/i1/||iq||/g
s/i2/||iw||/g
s/i3/||ie||/g
s/i4/||ir||/g
s/nyu3/n||u:e||/g
s/lyu/l||u:||/g
s/u:1/||u:q||/g
s/u:2/||u:w||/g
s/u:3/||u:e||/g
s/u:4/||u:r||/g
s/u:0/||u:s||/g
s/u1/||uq||/g
s/u2/||uw||/g
s/u3/||ue||/g
s/u4/||ur||/g
s/||aq||/ā/g
s/||aw||/á/g
s/||ae||/ǎ/g
s/||ar||/à/g
s/||eq||/ē/g
s/||ew||/é/g
s/||ee||/ě/g
s/||er||/è/g
s/||iq||/ī/g
s/||iw||/í/g
s/||ie||/ǐ/g
s/||ir||/ì/g
s/||oq||/ō/g
s/||ow||/ó/g
s/||oe||/ǒ/g
s/||or||/ò/g
s/||uq||/ū/g
s/||uw||/ú/g
s/||ue||/ǔ/g
s/||ur||/ù/g
s/||u:q||/ǖ/g
s/||u:w||/ǘ/g
s/||u:e||/ǚ/g
s/||u:r||/ǜ/g
s/||u:s||/ü/g
G
s/\([^\n]*\)\n\([^\n]*\)\n[^\n]*\n/\2\/\1\//
/\n/ b a
}
示例输入:
Some text containing for instance Chinese greeting /ni3
hao3/ and perhaps some other Chinese sentence, say /ni2
kan4, .../
预期产出:
Some text containing for instance Chinese greeting /nǐ
hǎo/ and perhaps some other Chinese sentence, say /ní
kàn, .../
我对sed(1)
的了解并不像我自己解决这个问题那么强大。因此,我请你帮助我。谢谢。
答案 0 :(得分:1)
根据我在您的问题中的理解,您需要为sed
命令指定address range:
sed '/\//,/\// {command1; command2; ...}'
然而,当/../
模式不多行时,这将会中断。这意味着您需要使多行全部。要确保每行只有一个/
:
sed 's_/_\n/_g' | sed {main sed command}
这也让人觉得如果你把所有行加到一行,你可以将多行引号视为一行:
cat myfile | tr '\n' ' ' | sed {your current commands}
P.S。另外我想指出一下你的“诀窍”有点瑕疵:
/\/.*\//
这是贪婪的,所以它不会正确处理同一行上的多个模式。因此,第二种方法可能无法正常工作。
编辑:好吧,这比我想象的更复杂(或者我太累了,看不到更简单的方法)。
要将线条重新组合在一起,您需要以“独特”方式拆分它们,以便稍后您可以分辨出脚本引入了哪些换行符。我建议这样做
sed 's_/_\n/\n_g'
以便每个/
获得自己的行。如果您看到一行由唯一的/
字符组成,您知道应该将其粘贴到上一个字符和下一个字符。首先,对文件执行上述sed
命令,然后使用地址范围/\//,/\//
进行替换,最后需要将这些行重新组合在一起。这可以通过
sed ':a $!{N;ba};s/\n\/\n/\//g'
所以我建议你最终解决这个问题。我不会为自己使用它而感到高兴,但你总是可以将它隐藏在shell函数或类似的东西中。
答案 1 :(得分:0)
最后,只需对原始sed(1)
代码进行少量改进即可轻松实现。也许它可以以某种方式更好地完成,但是当转换代码在“行范围”中工作时,我设法让它成为(对这个问题的本质并不重要的微小改进)而是在模式空间中读取整个文件,替换使用\001
(^A
)字符的换行符,让原始代码执行此操作,最后将^A
字符替换回换行符。这是:
#! /bin/sed -f
# pinyin2utf8.sed -- Convert US-ASCII Pinyin to UTF-8
# Copyright (C) 2012 Matous J. Fialka, <http://mjf.cz/>
# Released under the terms of The MIT License
#
# DESCRIPTION
# Script converts all occurences of US-ASCII encoded Pinyin text
# enclosed by the solidus characters pairs to UTF-8 encoded text.
#
# USAGE
# pinyin2utf8.sed filename [ > filename.out ]
#
# WARNINGS
# Script contains the ^A control character, usually displayed as
# mentioned in most text editors, that can be usually reproduced
# by pressing ^V ^A key sequence. The ^A control characters thus
# MUST NOT occure in the input stream. To find the sequences in
# the script lookup the y/// command in the code, please.
#
# In the US-ASCII encoded Pinyin to UTF-8 Pinyin conversion code
# special delimiting sequences of left and right parentheses are
# used and those two delimiting sequences of left or righ parens
# SHOULD NOT be used in the input stream.
: 0
$! {
N
b 0
}
# HERE BE DRAGONS
y/\n/^A/
y/\//\
/
: a
h
s/[^\n]*\n//
s/\n.*//
# CONVERSION CODE BEGINNING
s/ang1/(((aq)))ng/g
s/ang2/(((aw)))ng/g
s/ang3/(((ae)))ng/g
s/ang4/(((ar)))ng/g
s/eng1/(((eq)))ng/g
s/eng2/(((ew)))ng/g
s/eng3/(((ee)))ng/g
s/eng4/(((er)))ng/g
s/ing1/(((iq)))ng/g
s/ing2/(((iw)))ng/g
s/ing3/(((ie)))ng/g
s/ing4/(((ir)))ng/g
s/ong1/(((oq)))ng/g
s/ong2/(((ow)))ng/g
s/ong3/(((oe)))ng/g
s/ong4/(((or)))ng/g
s/an1/(((aq)))n/g
s/an2/(((aw)))n/g
s/an3/(((ae)))n/g
s/an4/(((ar)))n/g
s/en1/(((eq)))n/g
s/en2/(((ew)))n/g
s/en3/(((ee)))n/g
s/en4/(((er)))n/g
s/in1/(((iq)))n/g
s/in2/(((iw)))n/g
s/in3/(((ie)))n/g
s/in4/(((ir)))n/g
s/un1/(((uq)))n/g
s/un2/(((uw)))n/g
s/un3/(((ue)))n/g
s/un4/(((ur)))n/g
s/ao1/(((aq)))o/g
s/ao2/(((aw)))o/g
s/ao3/(((ae)))o/g
s/ao4/(((ar)))o/g
s/ou1/(((oq)))u/g
s/ou2/(((ow)))u/g
s/ou3/(((oe)))u/g
s/ou4/(((or)))u/g
s/ai1/(((aq)))i/g
s/ai2/(((aw)))i/g
s/ai3/(((ae)))i/g
s/ai4/(((ar)))i/g
s/ei1/(((eq)))i/g
s/ei2/(((ew)))i/g
s/ei3/(((ee)))i/g
s/ei4/(((er)))i/g
s/a1/(((aq)))/g
s/a2/(((aw)))/g
s/a3/(((ae)))/g
s/a4/(((ar)))/g
s/a1/(((aq)))/g
s/a2/(((aw)))/g
s/a3/(((ae)))/g
s/a4/(((ar)))/g
s/er2/(((ew)))r/g
s/er3/(((ee)))r/g
s/er4/(((er)))r/g
s/lyue/l(((u:)))e/g
s/nyue/n(((u:)))e/g
s/e1/(((eq)))/g
s/e2/(((ew)))/g
s/e3/(((ee)))/g
s/e4/(((er)))/g
s/o1/(((oq)))/g
s/o2/(((ow)))/g
s/o3/(((oe)))/g
s/o4/(((or)))/g
s/i1/(((iq)))/g
s/i2/(((iw)))/g
s/i3/(((ie)))/g
s/i4/(((ir)))/g
s/nyu3/n(((u:e)))/g
s/lyu/l(((u:)))/g
s/u:1/(((u:q)))/g
s/u:2/(((u:w)))/g
s/u:3/(((u:e)))/g
s/u:4/(((u:r)))/g
s/u:0/(((u:s)))/g
s/u1/(((uq)))/g
s/u2/(((uw)))/g
s/u3/(((ue)))/g
s/u4/(((ur)))/g
s/(((aq)))/ā/g
s/(((aw)))/á/g
s/(((ae)))/ǎ/g
s/(((ar)))/à/g
s/(((eq)))/ē/g
s/(((ew)))/é/g
s/(((ee)))/ě/g
s/(((er)))/è/g
s/(((iq)))/ī/g
s/(((iw)))/í/g
s/(((ie)))/ǐ/g
s/(((ir)))/ì/g
s/(((oq)))/ō/g
s/(((ow)))/ó/g
s/(((oe)))/ǒ/g
s/(((or)))/ò/g
s/(((uq)))/ū/g
s/(((uw)))/ú/g
s/(((ue)))/ǔ/g
s/(((ur)))/ù/g
s/(((u:q)))/ǖ/g
s/(((u:w)))/ǘ/g
s/(((u:e)))/ǚ/g
s/(((u:r)))/ǜ/g
s/(((u:s)))/ü/g
# CONVERSION CODE END
G
s/\([^\n]*\)\n\([^\n]*\)\n[^\n]*\n/\2\/\1\//
/\n/ b a
# HERE BE DRAGONS
y/^A/\
/
示例输入文字:
$ cat test.in
ni3 hao3
/ni3 hao3/
ni3 hao3 /ni3 hao3/
/ni3 hao3/ ni3 hao3
ni3 hao3 /ni3 hao3/ ni3 hao3
ni3 hao3 /ni3 hao3/ ni3 hao3 /ni3 hao3/
/ni3 hao3/ ni3 hao3 /ni3 hao3/
/ni3 hao3/ ni3 hao3 /ni3 hao3/ ni3 hao3
ni3 hao3 /ni3 hao3/ ni3 hao3 /ni3 hao3/ ni3 hao3
/ni3 hao3/ ni3 hao3 /ni3 hao3/ ni3 hao3 /ni3 hao3/
ni3 hao3 /ni3
hao3/ ni3 hao3
/ni3 hao3
ni3
hao3
ni3 hao3/ ni3 hao3
示例运行:
$ pinyin2utf8.sed test.in
ni3 hao3
/nǐ hǎo/
ni3 hao3 /nǐ hǎo/
/nǐ hǎo/ ni3 hao3
ni3 hao3 /nǐ hǎo/ ni3 hao3
ni3 hao3 /nǐ hǎo/ ni3 hao3 /nǐ hǎo/
/nǐ hǎo/ ni3 hao3 /nǐ hǎo/
/nǐ hǎo/ ni3 hao3 /nǐ hǎo/ ni3 hao3
ni3 hao3 /nǐ hǎo/ ni3 hao3 /nǐ hǎo/ ni3 hao3
/nǐ hǎo/ ni3 hao3 /nǐ hǎo/ ni3 hao3 /nǐ hǎo/
ni3 hao3 /nǐ
hǎo/ ni3 hao3
/nǐ hǎo
nǐ
hǎo
nǐ hǎo/ ni3 hao3
它似乎工作得很好(至少满足我的需求),因此我认为这个问题是关闭的。非常感谢所有参与的人,特别是Lev Levitsky先生!
P.S。:我还将代码here (GitHub)放在了可以跟踪未来可能发生的变化的地方。
P.S。 2:保存此答案时^A
个字符丢失了。现在,它们将在此处替换为ASCII表示。您必须将它们替换为二进制表示形式(在vi(1)
按插入模式下的^V ^A
)或使用GitHub version代替。
P.S。 3:我仍觉得^A
“黑客”非常难看。如果有人知道在这种情况下避免使用中间转换代码,尽管现在很简单,请分享您的想法。