2012-06-12 2 views
0

주어진 입력 스트림의 많은 단계별 변환 (대체)을 수행하는 sed(1) 스크립트가 작업 자체에 적합합니다. 이제는이 운영을 "/"인용 된 여러 줄 문자로 /로 제한하는 것이 필요합니다. 입력 된 스트림은 여러 줄의 "/"인용 문자열이 들어있는 파일입니다. 내 시퀀스를 s/// 명령으로 실행해야합니다. 나는 그것을 이루기가 꽤 어렵다는 것을 알고있다. sed(1) 그러나 나는 아직도 누군가가 어떻게 하는지를 알고 있기를 바란다. 내가 지금까지 가지고있는 스크립트 (그러나 한 줄 단위로 올바르게 작동한다)는 다음과 같다. sed specific - 큰 따옴표로 묶인 여러 줄 문자열 내에서 많은 대체를 수행합니다.

sed(1) "트릭"

는 처음에하고 스크립트의 말에, 나머지는 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)에 대한 저의 지식은이 문제를 스스로 해결할만큼 강력하지 않습니다. 내가 도와주기를 요청합니다. 고맙습니다. 나는 당신의 질문을 이해하는 바로는

+1

문제에 적용한 코드 [올바르게 형식화 된 (http://stackoverflow.com/editing-help) 코드를 게시하여 질문을 개선하십시오. 또한 ** relavant ** 오류 메시지를 그대로 보내 주시고 시간을내어 지금까지 수행 한 조치를 공유하여 스스로 조사하거나 해결하십시오. –

+2

AND 샘플 입력과 필요한 출력을 추가하십시오. 행운을 빕니다. – shellter

+0

질문이 지금 바뀌기를 바랍니다. – mjf

답변

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에게 감사드립니다!

추신 : 향후 변경 가능성을 추적 할 수있는 here (GitHub) 코드를 삽입했습니다.

P. 2 :이 대답을 저장하는 동안 ^A 문자가 손실되었습니다. 이제 그들은 여기서 ASCII 표현으로 대체됩니다. 이를 바이너리 표현으로 대체해야합니다 (삽입 모드에서 vi(1) 누르기 ^V ^A). 대신 GitHub version을 사용하십시오.

P. 3 : 나는 여전히 ^A "해킹"을 꽤 못 생겼다고 생각한다. 이 경우 중간 코드를 그대로 사용하면서 다른 사람이이 코드를 사용하지 않으려는 경우에는 아이디어를 공유하십시오.

1

, 당신은 sed 명령에 대한 address range를 지정해야합니다

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

그러나, 차례 휴식이 의지 할 때 /../ 패턴은 하지 멀티 라인이다. 즉, 모두 개를 여러 줄로 만들어야합니다. 하나의 / 줄에 거기에 있는지 확인하기 위해 수행

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

이 또한 처음에 하나에 모든 라인에 합류 경우 여러 줄을 처리 할 수있는 아이디어는 한 라인으로 인용 한 제공 :

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

추신 또한 나는 처음에 "트릭은"약간의 결함이 점에 유의하고 싶습니다 : 이것은 욕심

/\/.*\// 

, 제대로 같은 줄에 여러 개의 패턴을 처리하지 않도록. 이런 이유로 두 번째 접근법은 그대로 작동하지 않을 것입니다.

편집 : 좋아요, 이것은 내가 생각했던 것보다 더 복잡한 것으로 나타났습니다 (또는 나는 더 쉬운 방법을보기에는 너무 지쳤습니다).

줄을 다시 가져 오려면 "고유 한"방식으로 줄을 나누어야하므로 나중에 스크립트에서 줄 바꿈 중 어느 줄이 도입되었는지 알 수 있습니다. 나는 각 /가 자신의 라인을 얻을 수 있도록이

sed 's_/_\n/\n_g' 

처럼 그 일을하는 것이 좋습니다. 유일한 / 문자로 구성된 행이 표시되면 이전 행과 다음 행으로 연결해야한다는 것을 알고 있습니다.먼저 파일에서 위의 sed 명령을 수행 한 다음 주소 범위가 /\//,/\// 인 대체를 수행하고 마지막으로 다시 줄을 넣어야합니다. 이 작업은

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

과 같이 수행 할 수 있으므로 마지막으로이 작업을 수행하는 것이 좋습니다. 나는 이걸 직접 사용하는 것에 대해 행복하지 않을 것이지만 쉘 함수 또는 그 안에 뭔가 숨길 수 있습니다.

+0

안녕하세요. 솔루션에 몇 가지 문제가 있습니다. 예를 들어, 한 줄 더 추가로'sed (1)'명령을 쓰면, 원래의 형태로 깨진 줄을 다시 결합 할 수 있습니다 (사용자는 깨진 단락을 얻는 것을 좋아하지 않습니다). 또한이를 달성하기 위해 여러 스크립트를 함께 파이프 할 필요가 없기를 희망했습니다. 하지만 (선을 긋는) 주요 아이디어는 내게 맞는 것 같습니다. 이제 문제는 한 스크립트의 대체에 대해이 아이디어를 통합하는 방법입니다 (까다로울 수 있음). – mjf

+0

@mjf 출력을 정확히 입력 (linebreaks의 관점에서) 또는 그냥 괜찮은 보이게해야합니까? –

+0

예. linebreaks의 관점에서 정확히 동일합니다. 즉, 줄 바꿈을 포함하여 "/"따옴표 붙은 문자열을 모두 그대로 변환해야합니다. – mjf

관련 문제