표준 명령줄 유틸리티를 사용하여 키워드를 추출하시겠습니까?

표준 명령줄 유틸리티를 사용하여 키워드를 추출하시겠습니까?

예를 들어 위키낱말사전에 따르면 '언제'의 발음이다. enPR, IPA 및 X-SAMPA는 발음을 표시하는 서로 다른 방식입니다.

when:* {{a|US}} {{enPR|wĕn|hwĕn}}, {{IPA|/wɛn/|/ʍɛn/}}, {{X-SAMPA|/wEn/|/WEn/}}

when키워드 와 두 개의 IPA 발음을 추출하여 다른 줄에 배치하고 싶습니다 .

when wɛn
when ʍɛn

단어에는 하나, 둘 또는 그 이상의 IPA 발음이 있을 수 있으며 enPR 또는 X-SAMPA 발음이 있을 수도 있고 없을 수도 있습니다.

나는 목록 안의 목록인 PHP를 고려하고 있었지만 그것은 약간 과잉인 것처럼 보였고 가능하다면 사용자가 이를 설치하지 않아도 되도록 하고 싶습니다. awk, sed, cut 또는 기타 표준 Unix 명령줄 유틸리티에서 이를 수행할 수 있는 방법이 있습니까?

답변1

를 사용하면 sed다음과 같이 작성할 수 있습니다.

sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s//\1 \2/;s,/,,g;:1
     s/\(\([^ ]*\).*\)|/\1\n\2 /;t1'

분해(@slm, 감사합니다)

위의 명령은 다음과 같이 나눌 수 있습니다.

  1. 입력을 구문 분석 when: ... {IPA|...}하고 일치하지 않는 줄을 제거합니다.

    존재하다/pattern/!d; s//repl/

    [!] 패턴과 일치하지 않는 행을 삭제하고 다음 [s] 대체 명령에서 동일한 패턴을 재사용합니다(빈 패턴은 마지막 패턴을 재사용한다는 의미). [d] 를 사용하여 b일치하지 않는 행을 변경하지 않고 삭제할 수 있습니다 d. 또는 모든 행이 패턴과 일치한다는 것을 알고 있으면 s/pattern/repl/직접 사용할 수 있습니다.

    /\([^:]*\):.*{IPA|\([^}]*\).*/
    

    이 모드는 데이터를 2개의 블록으로 나눕니다. 첫 번째 블록은 입니다 when:. 이 코드는 \([^:]*\):a가 나타날 때까지 모든 문자를 가져와 :임시에 저장하도록 지시합니다. 바꾸다( \1).

    그 사이 :(포함) 의 모든 문자를 {IPA|건너뜁니다. 저장된 다음 비트는 입니다 IPA|. 이는 코드 블록을 사용하여 수행됩니다. \([^}]*\)즉, }a가 나타날 때까지 모든 코드를 저장합니다. 이는 변수( \2)에 저장됩니다.

    노트:sed문자열을 저장하고 싶을 때마다 괄호로 묶을 수 있습니다. 문자 그대로의 대괄호를 의미하지 않는다는 것을 알 수 \있도록 a로 이스케이프 처리해야 합니다 . sed이와 같이: \( savethis \).

    $ sed 's/\([^:]*\):.*{IPA|\([^}]*\).*/\1 \2/;' sample.txt
    when /wɛn/|/ʍɛn/
    
  2. 모든 슬래시 제거( /)

    이는 대체 구분 기호를 사용하기 때문에 더 복잡해 보입니다. 일반적으로 형식을 사용 s///g하지만 sed구분 기호를 동적으로 구성하므로 대신 쉼표( s,,,g)를 사용합니다. 블록은 이를 검색하여 /아무것도 없는 것으로 대체합니다.

    $ sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s//\1 \2/;s,/,,g;' sample.txt
    when wɛn|ʍɛn
    
  3. 각 IPA를 반복합니다.

     :1 s/\(\([^ ]*\).*\)|/\1\n\2 /;t1
    

    이는 솔루션에서 가장 복잡한 구성 요소입니다. 무슨 일이 일어나고 있는지 알기는 어렵지만 이 블록은 조건부 분기입니다.

     :label command(s) t label
    

    레이블은 이전 명령이 패턴 공간을 수정했는지 확인하는 "테스트"인 명령 :1입니다 . 그렇다면 라벨로 이동하여 .s/\(\([^ ]*\).*\)|/\1\n\2 /;t label1t1

  4. 루프 내의 명령

    잠시 동안 이를 꺼낸 label ... loop다음 IPA 예제를 늘려서 3까지 올리면 무슨 일이 일어나고 있는지 더 잘 볼 수 있습니다.

    {{IPA|/wɛn/|/ʍɛn/|/blah/}}
    

    이를 수행하기 위해 이전 명령을 사용하겠습니다.

    when wɛn|ʍɛn|blah
    

    지금 이것을 실행하면:

    $ echo "when wɛn|ʍɛn|blah" | sed 's/\(\([^ ]*\).*\)|/\1 \2 /;'
    

    우리는 이것을 얻습니다:

    when wɛn|ʍɛn
    when blah
    

    지금 무엇을 하고 있는지 볼 수 있나요? 예, 저도 마찬가지입니다. 좀 더 단순화하여 개행 문자( )를 제거 \n하고 더 짧은 문자열로 바꾸겠습니다.

    더 간단한 예

    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \2 /;'
    X C1|C2 X C3
    

    이제 여기서 일어나는 일은 코드가 \(\([^ ]*\).*\)|괄호를 중첩하여 다음과 같이 보이도록 하기 때문에 스마트하다는 것 입니다 ( ( ) ). 내부 괄호 안의 일치 항목은 공백이 아닙니다. 이것은 when문자열입니다. 외부 브래킷은 마지막 파이프( ) |앞의 모든 항목 과 일치합니다.

    이 코드 조각에 대한 또 다른 흥미로운 점은 대괄호가 외부 대괄호가 저장되고 \1내부 대괄호가 저장 되도록 순서가 지정되어 있다는 것입니다 \2. sed만나는 순서대로 번호가 매겨져 있기 때문입니다 .

    \1추가 합계로 스니펫을 확장하면 이를 확신할 수 있습니다 \2.

    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \1 \1 /;'
    X C1|C2 X C1|C2 X C1|C2 C3
    
    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \2 \2 /;'
    X C1|C2 X X C
    

    따라서 루프의 명령은 기본적으로 X두 번 실행됩니다. 한 번은 전체의 일부 X C1|C2(괄호 외부)로, 두 번째는 공간의 일부(괄호 내부)로 사용됩니다.

  5. 조건부 분기 반환

    좋아요, 그러면 브랜치는 기본적으로 #5의 명령을 호출할 것이며 IPA의 경우 2개 이상이 있습니다. sed분기 구성은 명령이 더 이상 대체 항목을 수정하지 않을 때까지 명령을 계속해서 다시 실행하며, 그 시점에서는 중지됩니다.

    $ echo "X C1|C2|C3" | sed ':1 s/\(\([^ ]*\).*\)|/\1\n\2 /; t1'
    X C1
    X C2
    X C3
    

위 내용이 앞으로 다른 행인들이 이 답변을 찾는 데 도움이 되기를 바랍니다.

답변2

Perl 스크립트에서 Perl 사용(처리 STDIN)

while(<>) {
    if(/^([^:]+):.*{{IPA\|([^}]+)}}/) { 
        print "$1 $_\n" foreach(split /\|/, $2); 
    }
}

또는 명령줄(파이프라인)에서

perl -ne ' if(/^([^:]+):.*{{IPA\|([^}]+)}}/) { print "$1 $_\n" foreach(split /\|/, $2); }'

답변3

bash와 grep 사용

line='when:* {{a|US}} {{enPR|wĕn|hwĕn}}, {{IPA|/wɛn/|/ʍɛn/}}, {{X-SAMPA|/wEn/|/WEn/}}'
IFS=$': \t' read -ra words <<< "$line"
for item in "${words[@]}"; do
    if [[ $item == "{{IPA|"* ]]; then
        grep -o '/[^/]\+/' <<< "$item" | while read -r pronunc; do
             echo "${words[0]} ${pronunc//\//}"
        done
    fi
done

관련 정보