Удалить первое заглавное слово после точки - PullRequest
3 голосов
/ 13 июня 2019

Я хотел бы иметь возможность удалить первое слово, написанное заглавными буквами после периода.Цель состоит в том, чтобы удалить первое слово, написанное заглавными буквами, даже если предложения в одной строке два.На самом деле, как я покажу в этом примере, первое слово строки было опущено, но появляется первое слово второго предложения.

Для первого предложения первой строки я решил проблему следующим образом:начиная с 2 вместо 1:

вот код

BEGIN { FS="[^[:alpha:]']+"; OFS=" "} 
{
   parola=" "
   max_nr=0

   prec=""

   for (i=2; i<=NF; i++) {
        if ($i ~ /[[:punct:][:digit:]]+[:space:]*[A-Z][']{0,1}[A-Z]{0,1}[a-z]+/){
            continue
        }
        else{
            if ($i ~ /[A-Z][']{0,1}[A-Z]{0,1}[a-z]+/){

                if(!(prec=="")){

                    prec=prec" "$i
                }
                else{
                    prec=$i              
                }
            }     
            else {

                if(!(prec=="")){

                    words[prec]
                    prec=""    
                  }
            }

            if (i==NF) {
                max_nr=max_nr+1  
                for (word1 in words) {
                    for (word2 in words) {
                        if (word1 != word2) {
                            print parola"" word1","word2
                        }
                    }

                    delete words[word1]
                }                
            }
            }
}  
}   
END{
    print FILENAME" "FNR
    print i
    print max_nr
}

Это содержимое test.txt:

Today Jonathan played soccer with Martin. After the game, Martin and Jonathan were thirsty and then drank a fresh Lemon Soda. 
Paolo went to Lisbon with an Easyjet plane. During the trip he met two of his dear friends, Peter and John.

Это результаткоманда:

awk -f script.awk test.txt> output.csv

Lisbon,During
Lisbon,John
Lisbon,Peter
Lisbon,Easyjet
During,John
During,Peter
During,Easyjet
John,Peter
John,Easyjet
Peter,Easyjet
Jonathan,Martin After
Jonathan,Lemon Soda
Jonathan,Martin
Martin After,Lemon Soda
Martin After,Martin
Lemon Soda,Martin

Ожидаемый результат должен быть:

Lisbon,John
Lisbon,Peter
Lisbon,Easyjet
John,Peter
John,Easyjet
Peter,Easyjet
Jonathan,Martin
Martin,Lemon Soda
Jonathan,Lemon Soda

Есть предложения?

Ответы [ 2 ]

2 голосов
/ 13 июня 2019

Не пытаясь сделать всю работу за вас ( Я предоставил решение для этого ранее ), просто решите конкретную проблему, о которой вы задали этот вопрос:

Вы используете FS="[^[:alpha:]']+", поэтому невозможно указать заданное поле («слово»), если разделитель до него был . или что-то еще. Используйте FS='[.]' или подобное в качестве отправной точки, и тогда вы будете знать, что разделитель перед каждым полем был началом строки или ., а затем вы можете использовать split($i,f,/[^[:alpha:]']+/), чтобы изолировать каждое подполе («слово»). ) в этом поле («предложение»). e.g.:

$ cat tst.awk
BEGIN { FS="[[:space:]]*[.][[:space:]]*" }
{
    for (sentenceNr=1; sentenceNr<=NF; sentenceNr++) {
        sentence = $sentenceNr
        numWords = split(sentence,words,/[^[:alpha:]\047]+/)
        for (wordNr=2; wordNr<=numWords; wordNr++) {
            word = words[wordNr]
            if ( word ~ /^[[:upper:]]/ ) {
                print NR, sentenceNr, wordNr, word
            }
        }
    }
}

$ awk -f tst.awk file
1 1 2 Jonathan
1 1 6 Martin
1 2 4 Martin
1 2 6 Jonathan
1 2 14 Lemon
1 2 15 Soda
2 1 4 Lisbon
2 1 7 EasyJet
2 2 11 Peter
2 2 13 John

Обратите внимание, что с учетом этого ввода:

$ cat file
Today Jonathan played soccer with Martin. After the game, Martin and Jonathan were thirsty and then drank a fresh Lemon Soda.
Paolo went to Lisbon with an EasyJet plane. During the trip he met two of his dear friends, Peter and John.
May lost her home. 10 Downing St is where the PM lives.

выше будет выводить:

$ awk -f tst.awk file
1 1 2 Jonathan
1 1 6 Martin
1 2 4 Martin
1 2 6 Jonathan
1 2 14 Lemon
1 2 15 Soda
2 1 4 Lisbon
2 1 7 EasyJet
2 2 11 Peter
2 2 13 John
3 2 2 Downing
3 2 3 St
3 2 7 PM

если «Даунинга» не должно быть, измените код на:

$ cat tst.awk
BEGIN { FS="[[:space:]]*[.][[:space:]]*" }
{
    for (sentenceNr=1; sentenceNr<=NF; sentenceNr++) {
        numWords = split($sentenceNr,words,/[^[:alpha:]\047]+/)
        isSubsequent = 0
        for (wordNr=1; wordNr<=numWords; wordNr++) {
            word = words[wordNr]
            if ( word ~ /^[[:upper:]]/ ) {
                if ( isSubsequent++ ) {
                    print NR, sentenceNr, wordNr, word
                }
            }
        }
    }
}

$ awk -f tst.awk file
1 1 2 Jonathan
1 1 6 Martin
1 2 4 Martin
1 2 6 Jonathan
1 2 14 Lemon
1 2 15 Soda
2 1 4 Lisbon
2 1 7 EasyJet
2 2 11 Peter
2 2 13 John
3 2 3 St
3 2 7 PM
1 голос
/ 13 июня 2019

Следующее предполагает, что ваш текст следует основному правилу пунктуации. Символ пунктуации сопровождается пробелом. Если у вас есть это, вы можете использовать GNU awk, чтобы очень легко извлечь интересующие вас слова, определив записи и шаблоны полей. Запись считается предложением, которое заканчивается любым из следующих символов .?!. Слова, написанные заглавными буквами, распознаются по шаблону: [A-Z][a-z]* Теперь все просто:

awk 'BEGIN{ RS="[.?!][[:space:]]*"; FPAT="([[:space:]]+[[:upper:]][[:alnum:]]*)+"}
     { print "record",NR,":",$0 }
     { for(i=1;i<=NF;++i) print "field",i,":",$i }' file

Здесь мы обновляем разделитель записей RS, чтобы включить в него различные возможные пробелы из класса [[:space:]]. Это гарантирует, что перед первым словом не будет пробела. Все остальные слова, написанные с заглавной буквы, можно затем выбрать, проверив шаблоны полей FPAT="([[:space:]][[:upper:]][[:alnum:]]*)+", которые представляют собой последовательность общих слов, разделенных пробелом. Обратите внимание, что поля всегда начинаются с пробела или символа новой строки. Это можно легко очистить с помощью простой замены:

Это выводит:

record 1 : Today Jonathan played soccer with Martin
field 1 :  Jonathan
field 2 :  Martin
record 2 : After the game, Martin and Jonathan were thirsty and then drank a fresh Lemon Soda
field 1 :  Martin
field 2 :  Jonathan
field 3 :  Lemon Soda
record 3 : Paolo went to Lisbon with an Easyjet plane
field 1 :  Lisbon
field 2 :  Easyjet
record 4 : During the trip he met two of his dear friends, Peter and John
field 1 :  Peter
field 2 :  John

Который теперь можно адаптировать к задаче ОП (с коррекцией пространства для полей):

awk 'BEGIN{ RS="[.?!][[:space:]]*"; FPAT="([[:space:]]+[[:upper:]][[:alnum:]]*)+"}
     { for (i=1;i<=NF;++i) { 
           w=$i; gsub(/[[:space:]]+/," ",w);
           w=substr(w,2); words[w]
       }
     }
     { for (w1 in words) { 
           for (w2 in words) if(w1 != w2) print w1,w2
           delete words[w1]
        }
     }' file

возвращается:

Jonathan Martin
Jonathan Lemon Soda
Jonathan Martin
Lemon Soda Martin
Lisbon Easyjet
John Peter
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...