0

sed(1)タスク自体に適した、特定の入力ストリームの多くの段階的な変換 (置換) を行うスクリプトがあります。ここで、これらの操作を「/」で囲まれた複数行の文字列のみに制限する必要があります。s///入力ストリームは、一連のコマンドを実行するために必要な複数行の「/」引用符付き文字列を含む単純なテキスト ファイルです。それを達成するのは非常に難しいことはわかっていsed(1)ますが、それでも誰かが方法を知っていることを願っています. これまでのスクリプト (ただし、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)この問題を自分で解決するには強力ではありません。そのため、私はそれを手伝ってくれるようお願いします。ありがとうございました。

4

2 に答える 2

1

あなたの質問で私が理解していることから、コマンドのアドレス範囲を指定する必要があります。sed

sed '/\//,/\// {command1; command2; ...}'

/../ただし、パターンが複数行でない場合、これは順番に壊れます。つまり、それらすべてを複数行にする必要があります。/1行に1つだけであることを確認するには、次のようにします。

sed 's_/_\n/_g' | sed {main sed command}

これは、最初にすべての行を 1 つに結合した場合、複数行の引用符を 1 行として扱うことができるという考えも与えます。

cat myfile | tr '\n' ' ' | sed {your current commands}

PS また、最初の「トリック」には少し欠陥があることに注意してください。

 /\/.*\//

これは貪欲なので、同じ行で複数のパターンを正しく処理しません。このため、2 番目の方法はおそらくそのままでは機能しません。

編集:わかりました、これは思ったよりも複雑でした(または、疲れすぎて簡単な方法がわかりません)。

行を元に戻すには、「独自の」方法で行を分割する必要があります。これにより、スクリプトによってどの改行が導入されたかを後で知ることができます。このようにすることをお勧めします

sed 's_/_\n/\n_g'

それぞれ/が独自の行を取得するようにします。唯一の文字で構成される行が表示された場合は、/前の行と次の行に貼り付ける必要があることがわかります。したがって、最初sedにファイルに対して上記のコマンドを実行し、次にアドレス範囲 as で置換を実行し、/\//,/\//最後に行を元に戻す必要があります。これはで行うことができます

sed ':a $!{N;ba};s/\n\/\n/\//g'

したがって、最終的にこれにパイプすることをお勧めします。私はこれを自分で使わなければならないことに満足していませんが、シェル関数などの中にいつでも隠すことができます。

于 2012-06-12T21:26:05.633 に答える
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 氏に感謝します。

PS: また、将来の変更の可能性を追跡できるコードをここ (GitHub)に配置しました。

PS 2:^Aこの回答の保存中に文字が失われました。現在、これらはここで ASCII 表現に置き換えられています。それらをバイナリ表現に置き換えるか (挿入モードでvi(1)印刷中)、代わりにGitHub バージョンを使用する必要があります。^V ^A

PS 3: 私はまだ^A「ハック」が非常に醜いと感じています。この場合、中間の変換コードを今のように単純にしながら回避する方法を誰かが知っている場合は、アイデアを共有してください。

于 2012-06-14T23:39:17.373 に答える