Как объединить все слова предложения, извлеченные с помощью регулярного выражения? - PullRequest
5 голосов
/ 08 июня 2019

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

My friend John met Beatrice and Lucio.

Результат, который я хотел бы получить:

  • Джон, Беатрис
  • Джон, Лучио
  • Беатрис, Lucio

Мне удалось получить все слова, которые начинаются с заглавной буквы, за исключением слова в начале строки через регулярное выражение.Регулярное выражение:

*cat gov.json | grep -oP "\b([A-Z][a-z']*)(\s[A-Z][a-z']*)*\b | ^(\s*.*?\s).*" > nodes.csv*

Узлам удалось ввести их по отдельности в столбце, то есть:

  • Джон
  • Беатрис
  • Люсио

Теперь цель состоит в том, чтобы создать возможные комбинации между именами, которые начинаются с заглавной буквы, и поместить их в файл.Есть предложения?

Ответы [ 5 ]

6 голосов
/ 08 июня 2019

Если порядок пар в выходных данных не имеет значения:

$ cat tst.awk
BEGIN { FS="[^[:alpha:]]+"; OFS=", " }
{
    for (i=2; i<=NF; i++) {
        if ($i ~ /^[[:upper:]]/) {
            words[$i]
        }
    }
}
END {
    for (word1 in words) {
        for (word2 in words) {
            if (word1 != word2) {
                print word1, word2
            }
        }
        delete words[word1]
    }
}

$ awk -f tst.awk file
Beatrice, Lucio
Beatrice, John
Lucio, John

Если порядок имеет значение, то:

$ cat tst.awk
BEGIN { FS="[^[:alpha:]]"; OFS=", " }
{
    for (i=2; i<=NF; i++) {
        if ($i ~ /^[[:upper:]]/) {
            if ( !seen[$i]++ ) {
                words[++numWords] = $i
            }
        }
    }
}
END {
    for (word1nr=1; word1nr<=numWords; word1nr++) {
        word1 = words[word1nr]
        for (word2nr=word1nr+1; word2nr<=numWords; word2nr++) {
            word2 = words[word2nr]
            print word1, word2
        }
    }
}

$ awk -f tst.awk file
John, Beatrice
John, Lucio
Beatrice, Lucio

В приведенном выше тексте file содержит исходный ввод, например, My friend John met Beatrice and Lucio.

4 голосов
/ 08 июня 2019

Вот еще один awk скрипт, выполняющий задачу, создающий вывод при чтении ввода.

script.awk разрешено дублирование имен.

BEGIN {FPAT =  " [[:upper:]][[:alpha:]]+"}
{
    for (i = 1; i <= NF; i++ ) {
        for (name in namesArr) {
            namePairsArr[pairsCount++] = namesArr[name] $i;
        }
        namesArr[namesCount++] = $i;
    }   
}
END {for (i = 0; i < pairsCount; i++) print namePairsArr[i];}

Если повторяющиеся имена не разрешены, script.awk:

BEGIN {FPAT =  " [[:upper:]][[:alpha:]]+"}
{
    for (i = 1; i <= NF; i++ ) {
        if (nameSeenArr[$i]) continue;
        nameSeenArr[$i] = 1;
        for (name in namesArr) {
              namePairsArr[pairsCount++] = namesArr[name] $i;
        }
        namesArr[namesCount++] = $i;
    }
}
END {for (i = 0; i < pairsCount; i++) print namePairsArr[i];}**

пробег

awk -f script.awk gov.json > nodes.csv

Пример входного файла:

My friend John met Beatrice and Lucio
My friend Johna met Beatricea and Lucioa

пример вывода:

 John Beatrice
 John Lucio
 Beatrice Lucio
 John Johna
 Beatrice Johna
 Lucio Johna
 John Beatricea
 Beatrice Beatricea
 Lucio Beatricea
 Johna Beatricea
 John Lucioa
 Beatrice Lucioa
 Lucio Lucioa
 Johna Lucioa
 Beatricea Lucioa
2 голосов
/ 08 июня 2019

Если у вас есть результаты в массиве, вы можете выполнить цикл с

names=( John Beatrice Lucio )
max=${#names[@]}

for ((i1=0; i1<max; i1++)); do
  for ((i2=i1+1; i2<max; i2++)); do
    echo "${names[$i1]}, ${names[$i2]}"
  done
done

Если вам не нужно много имен (длина arglist), вы можете использовать

set -- John Beatrice Lucio
for a; do
    shift
    for b; do
        printf "%s, %s\n" "$a" "$b"
    done
done
2 голосов
/ 08 июня 2019

Если вам нужны все возможные пары имен, допустим, вы создали names.txt , содержащий:

    John
    Beatrice
    Lucio

Я бы попробовал это в bash:

  $ for n in `cat names.txt`
  > do for m in `cat names.txt`
  >   do if [ $m != $n ]; then
  >        echo $n, $m
  >      fi
  >   done
  > done
  John, Beatrice
  John, Lucio
  Beatrice, John
  Beatrice, Lucio
  Lucio, John
  Lucio, Beatrice
1 голос
/ 08 июня 2019

Если единственной проблемой будет первое слово нашей строки, мы просто добавим . в нашем выражении:

.([A-Z][a-z']+)

или мы добавим пробел в качестве левой границы:

(\s+)([A-Z][a-z']+)(\s+)?

Наше желаемое слово находится в этой группе захвата:

([A-Z][a-z']+)

Демо

, но это не получится, если у нас будут такие случаиas:

My friend Alice O'Neal met Beatrice and Lucio

, для которого мы можем расширить нашу желаемую группу вывода.

RegEx

Если это выражение не нужно и вы хотите изменить его, перейдите по этой ссылке на regex101.com .

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...