Позиция (по количеству слов) всех повторений слова в текстовом файле

Поскольку устройства-роботы имеют разные IP-адреса, самым простым способом будет создание моста Linux с двумя интерфейсами Ethernet в качестве портов. Что-то вроде

ip link add name br0 type bridge
ip link set enp3s0 master br0
ip link set enp6s0 master br0

Затем установите одиночный IP-адрес на внутреннем интерфейсе br0:

.

ip addr add 10.0.0.1/24 dev br0

и вы должны быть в порядке, без коммутатора, свисающего с хвоста коробки, но все по-прежнему в той же сети.

И пожалуйста, пожалуйста , не используйте Kali Linux для таких вещей. Прочтите это и сделайте себе одолжение и переключитесь на какой-нибудь дистрибутив (на основе Debian -, так как Kali также основана на Debian -), который предназначен для повседневной работы. Вы столкнетесь с гораздо меньшими трудностями. И все блестящие инструменты, которые есть у Kali, также могут быть установлены.

6
11.06.2020, 17:16
9 ответов

Используйте команду tr, чтобы заменить все пробелы одной новой строкой (с помощью параметра сжатия ).

Передайте это в nl -ba, который последовательно нумерует каждую строку (и, следовательно, слово ).

Передайте это grep -F для нужного вам слова. Это покажет номер и текст только для этих слов.

awk также сделал бы это в одном процессе, но, вероятно, выглядел бы более сложным.

3
28.04.2021, 23:22

Вот один из способов, с использованием инструментов GNU:

$ tr ' ' '\n' < file | tr -d '[:punct:]' | grep. | grep -nFx iPhone
25:iPhone
54:iPhone
58:iPhone

Первый trзаменяет все пробелы символами новой строки, а затем второй удаляет все знаки препинания (, так что iPhone,можно найти как слово ). grep.гарантирует, что мы пропустим все пустые строки (, которые мы не хотим считать ), а grep -nдобавляет номер строки к выводу. Затем -Fговорит grepне рассматривать ввод как регулярное выражение, а -xчто он должен находить только совпадения, охватывающие всю строку (, так что jobне будет считаться совпадением. дляjobs). Обратите внимание, что цифры, которые вы дали в своем вопросе, были на единицу меньше.

Если вам нужны только цифры,вы можете добавить еще один шаг:

$ tr ' ' '\n' < file | tr -d '[:punct:]' | grep. | grep -nFx iPhone | cut -d: -f1
25
54
58

Как было указано в комментариях, у этого все еще будут проблемы со «словами», такими как aren'tили double-barreled. Вы можете улучшить это, используя:

tr '[[:space:][:punct:]]' '\n' < file | grep. | grep -nFx iPhone
6
28.04.2021, 23:22

Альтернатива сsed:

sed -e '/^$/d' -e 's/^[[:blank:]]*//g' < file | sed 's/[[:blank:]]/\n/g' | grep -ion "iphone"

Выход:

25:iPhone
54:iPhone
58:iPhone
2
28.04.2021, 23:22

Я экспериментировал (прямо сейчас!)с чем-то подобным :количеством слов. Вот так вы видите, как выглядят «слова»:

]# cat iphone | tr -s [:space:] '\n' |sort|uniq -c|sort -n  |grep phone
      1 phone,
      1 phones
      1 phones,

]# cat iphone | tr -d [:punct:] | tr -s [:space:] '\n' |sort|uniq -c|sort -n  |grep phone
      1 phone
      2 phones

Этот трюк (?)|sort|uniq -c|sort -nдает хороший обзор.

  2 Apple
  2 Pro
  2 a
  2 and
  2 company
  2 more
  2 phones
  2 to
  3 11
  3 iPhone
  3 its
  4 at
  6 the

Выглядит красиво, но сверху:

  1 1000
  1 1100
  1 700
  1 750
  1 90minute

Доллары, запятая и минус исчезли... по крайней мере, выглядит аккуратно.


Быстрое исправление заключается в определении некоторых общих вставок, которые не будут появляться в (естественном языке )"слово". А затем используйте ^анкоринг$ с одной или обеих сторон.

]# cat iphone | tr -d '.,;"!?' | tr -s [:space:] '\n' | grep -n phone 
21:phones
30:phone
72:phones

]# cat iphone | tr -d '.,;"!?' | tr -s [:space:] '\n' | grep -n ^phone$
30:phone

И вы можете найти такие вещи, как маленькие -цифры:

]# cat iphone | tr -d '.,;"!?' | tr -s [:space:] '\n' | grep -n '1[012]'
27:11
56:11
60:11
64:$1000
66:$1100

tr|sed|grep(лучшее простое решение)

Это обрабатывает некоторые случаи (хорошо все в этом @ *#! текст; )и дает 81 слово, например wc. Для правильной нумерации не должно быть начальных пробелов. Глупое (, но не слишком )разбиение выполняется с помощью tr, затем sedудаляет конечные знаки препинания :здесь только запятая и точка. А затем grepномера и фильтры импровизированные.

]# <iphone  tr -s ' \t' '\n' | sed -E 's/(.+)[.,]/\1/' | grep -En  '[\$-]|campus|i*[pP]hone$|entry' 
25:iPhone
28:entry-level
29:phone
33:$700
36:$750
54:iPhone
58:iPhone
63:$1000
65:$1,100
74:90-minute
81:campus

Это i*[pP]hone$не не находит форму множественного числа. Это не будет работать с запятой в конце, см. выше. Запятые исчезли, кроме цен.

Чтобы отделить «входной -уровень», вы можете просто добавить знак минус к trSET1.

Я думаю, что это хороший пример того, как каждый инструмент выполняет один естественный шаг.

0
28.04.2021, 23:22

Создайте функцию.

$ whereword(){ grep -ion "$1" -<<<$(egrep -o "[^[:blank:]]+" "$2"); }

$ whereword iPhone tmp.txt
25:iPhone
54:iPhone
58:iPhone

$ whereword "aren't" tmp.txt
14:aren't
0
28.04.2021, 23:22

[Интересно, как вы получили эти числа --, если я выделю текст до 1-го iPhoneи направлю его в wc -w, я получу 24. До 2-го iPhone, я получу 53, а не 54. Значит, они не совпадают, в какую бы сторону я их не сдвигал]

Предполагая, что a)количество должно быть основано на 1 -, b)слова разделяются пробелами (с использованием того же определения «слова», что и wc -w), и c)GNU grep используется, это будет намного проще:

grep -Po '\S+' file | grep -n iPhone

25:iPhone
54:iPhone
58:iPhone

[это также будет соответствовать iPhoneyили XiPhone, но не iphone; если вы хотите, чтобы регистр соответствовал всему слову без учета регистра, используйте ... | grep -nwi iPhone]

Это также легче адаптировать к другому определению «слова»; например, для слова = последовательность любых символов, кроме элементов управления, пробелов (, разделителей )и знаков препинания:

grep -Po '[^\pC\pZ\pP]+' file | grep -n iPhone

26:iPhone
56:iPhone
60:iPhone

Или слово = буквы, знаки, цифры и некоторые символы и знаки препинания, такие как $, _, '+ неправильно использованная «левая кавычка» (U+2019 )вместо апострофа вaren’t:

grep -Po "[\pL\pM\pN'\x{2019}\$]+" file | grep -n iPhone

25:iPhone
55:iPhone
59:iPhone
0
28.04.2021, 23:22

Использование наиболее распространенной интерпретации «слова» для разбора английского текста (, т. е. что grep -wсчитается словом и что \wозначает в инструментах, которые принимают это как значение «символа, составляющего слово» в регулярных выражениях )который представляет собой «строку букв, цифр и/или символов подчеркивания» aren’t, не является словом, поэтому:

$ cat tst.awk
BEGIN { FS="[^[:alnum:]_]+" }
{
    for (i=1; i<=NF; i++) {
        numWords++
        if ($i == tgt) {
            print numWords
        }
    }
}

$ awk -v tgt="iPhone" -f tst.awk file
26
57
61

$ awk -v tgt="aren’t" -f tst.awk file
$

$ awk -v tgt="aren" -f tst.awk file
14

или если aren’tслово, то:

$ cat tst.awk
BEGIN { FS="[^[:alnum:]_’]+" }
{
    for (i=1; i<=NF; i++) {
        numWords++
        if ($i == tgt) {
            print numWords
        }
    }
}

$ awk -v tgt="iPhone" -f tst.awk file
25
56
60

$ awk -v tgt="aren’t" -f tst.awk file
14

$ awk -v tgt="aren" -f tst.awk file
$

Правильное решение зависит от вашего определения слова. Например, ни один из вышеперечисленных не считает $1,000словом -idk, если это проблема или нет для вашего приложения. Если это,вот сценарий, который может быть ближе к вашей интерпретации «слова» (с использованием GNU awk для FPAT):

$ cat tst.awk
BEGIN {
    FPAT = "([[:alpha:]]+[’'][[:alpha:]]+)|([$]?[0-9]+(,[0-9]+)*([.][0-9]+)?%?)|([[:alnum:]_]+)"
}
{
    for (i=1; i<=NF; i++) {
        numWords++
        print numWords, "<" $i ">"
        if ($i == tgt) {
            print numWords
        }
    }
}

а вот «слова», которые он распознает в вашем образце ввода:

$ awk -f tst.awk file
1 <On>
2 <Tuesday>
3 <in>
4 <a>
5 <sign>
6 <that>
7 <Apple>
8 <is>
9 <paying>
10 <attention>
11 <to>
12 <consumers>
13 <who>
14 <aren’t>
15 <racing>
16 <to>
17 <buy>
18 <more>
19 <expensive>
20 <phones>
21 <the>
22 <company>
23 <said>
24 <the>
25 <iPhone>
26 <11>
27 <its>
28 <entry>
29 <level>
30 <phone>
31 <would>
32 <start>
33 <at>
34 <$700>
35 <compared>
36 <with>
37 <$750>
38 <for>
39 <the>
40 <comparable>
41 <model>
42 <last>
43 <year>
44 <Apple>
45 <kept>
46 <the>
47 <starting>
48 <prices>
49 <of>
50 <its>
51 <more>
52 <advanced>
53 <models>
54 <the>
55 <iPhone>
56 <11>
57 <Pro>
58 <and>
59 <iPhone>
60 <11>
61 <Pro>
62 <Max>
63 <at>
64 <$1,000>
65 <and>
66 <$1,100>
67 <The>
68 <company>
69 <unveiled>
70 <the>
71 <new>
72 <phones>
73 <at>
74 <a>
75 <90>
76 <minute>
77 <press>
78 <event>
79 <at>
80 <its>
81 <Silicon>
82 <Valley>
83 <campus>
0
28.04.2021, 23:22

Альтернатива GNU awk, разбиение на отдельные пробелы или сочетание точки и новой строки

awk 'BEGIN{RS=" |\\.\n"} $0~/iPhone/{print NR}' file1
0
28.04.2021, 23:22

Не отставать от идеи, что слово — это то, что wcсчитается словом:

A word is a non-zero-length sequence of characters delimited by white space.

Мы можем разделить файл на последовательности не -пробелов в каждой строке с помощью grep -Eo '[^[:space:]]+' file, затем удалить tr -d '[:punct:]'оставшиеся (существующие )знаки пунктуации и, наконец, grep (нечувствительны к регистру. )по интересующему словуgrep -in 'phone'

$ grep -Eo '[^[:space:]]+' file | tr -d '[:punct:]' | grep -in 'phone'
20:phones
25:iPhone
29:phone
54:iPhone
58:iPhone
71:phones

Обратите внимание, что удаление знаков пунктуации в этом случае не меняет положение слов в строке. Опция -iвыбирает как Phone, так и phone, как показано.

Для случая словаiPhone:

$ grep -Eo '[^[:space:]]+' file | tr -d '[:punct:]' | grep -in 'iphone'
25:iPhone
54:iPhone
58:iPhone

Это должна быть правильная нумерация слов (Не 24, 54 и 58, как вы написали ).

0
28.04.2021, 23:22

Теги

Похожие вопросы