Как фильтровать данные из текста с помощью grep или sed?

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

Входной файл: file.txt

id,created_at,text 842433,2017-05-20 14:45:05,goldring.com was just registered https://t.co/xt9345d 336353,2017-05-20 14:45:04,stretch.com was just registered https://t.co/QBEX965hf 84244e,2017-05-20 14:45:03,"Auctions were started for wantit1.com, wantit2.com, wantit3.com and wantit4.com" 842434,2017-05-20 14:45:02,"Auctions were started for sidefun.com, coffeetec.com, lifeout.com and new-fun-boys.com"

Ожидающий вывод:

wantit1 wantit2 wantit3 wantit4 sidefun coffeetec lifeout new-fun-boys

Код У меня есть:

cat file.txt | while read line; do echo "$line" >> out1.txt done
2
задан 21 May 2017 в 17:48

9 ответов

Для вашего конкретного ввода это будет работать:

grep -Po '\s[a-z1-9-]{2,}(?=\..{2,4})' file.txt
-P: сделать нас способными смотреть вперед. -o: показывать только совпадения. \s: искать только те, которые начинаются с пробела [a-z1-9-]{2,}. Последует любой буквенно-цифровой символ или дефис, как минимум 2 или более. (?=\..{3}): это будет заканчиваться точкой и от 2 до 4 символов (суффикс домена), но не включать его.

Вот результат:

wantit1  
wantit2  
wantit3  
wantit4  
sidefun  
coffeetec  
lifeout  
new-fun-boys  

Лучшая идея (на основе вашего комментария) заключается в использовании:

awk '(/2017-05-20/ && /Auctions were started/)' file.txt | grep -Po '\s[a-z1-9-]{1,}(?=\..{2,4})'
2
ответ дан 22 May 2018 в 22:24
  • 1
    Это работало так, как я хочу, но у меня еще есть другой вопрос. Я хочу получить данные только с датой '2017-05-20, и вывод должен быть отсортирован по длине имени домена. – Kasaram Bala 24 May 2017 в 05:33
  • 2
    @ KasaramBala Я обновил свой ответ для первой части вашего вопроса, для второго у меня есть другой ответ: здесь . – Ravexina 24 May 2017 в 09:44

Для вашего конкретного ввода это будет работать:

grep -Po '\s[a-z1-9-]{2,}(?=\..{2,4})' file.txt -P: сделать нас способными смотреть вперед. -o: показывать только совпадения. \s: искать только те, которые начинаются с пробела [a-z1-9-]{2,}. Последует любой буквенно-цифровой символ или дефис, как минимум 2 или более. (?=\..{3}): это будет заканчиваться точкой и от 2 до 4 символов (суффикс домена), но не включать его.

Вот результат:

wantit1 wantit2 wantit3 wantit4 sidefun coffeetec lifeout new-fun-boys

Лучшая идея (на основе вашего комментария) заключается в использовании:

awk '(/2017-05-20/ && /Auctions were started/)' file.txt | grep -Po '\s[a-z1-9-]{1,}(?=\..{2,4})'
2
ответ дан 18 July 2018 в 12:58

Для вашего конкретного ввода это будет работать:

grep -Po '\s[a-z1-9-]{2,}(?=\..{2,4})' file.txt -P: сделать нас способными смотреть вперед. -o: показывать только совпадения. \s: искать только те, которые начинаются с пробела [a-z1-9-]{2,}. Последует любой буквенно-цифровой символ или дефис, как минимум 2 или более. (?=\..{3}): это будет заканчиваться точкой и от 2 до 4 символов (суффикс домена), но не включать его.

Вот результат:

wantit1 wantit2 wantit3 wantit4 sidefun coffeetec lifeout new-fun-boys

Лучшая идея (на основе вашего комментария) заключается в использовании:

awk '(/2017-05-20/ && /Auctions were started/)' file.txt | grep -Po '\s[a-z1-9-]{1,}(?=\..{2,4})'
2
ответ дан 24 July 2018 в 20:04

Вот несколько вариантов:

Подход KISS с использованием двух greps:

$ grep 'Auctions were started for' file | grep -o '\S*\.com'
wantit1.com
wantit2.com
wantit3.com
wantit4.com
sidefun.com
coffeetec.com
lifeout.com
new-fun-boys.com

Более элегантный:

$ perl -lne 'if (/"Auctions were started for (.*)"/) {print for split(/, | and /, $1)}' file
wantit1.com
wantit2.com
wantit3.com
wantit4.com
sidefun.com
coffeetec.com
lifeout.com
new-fun-boys.com
3
ответ дан 22 May 2018 в 22:24

Вы можете легко достичь этого с помощью комбинации grep, чтобы найти все строки в file.txt, содержащие текст «Аукционы были запущены для» и sed, чтобы извлекать только имена доменов без TLD и печатать по одной в строке :

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt | sed -r 's/and |,|.com//g;y/ /\n/'

Вот разбивка команды:

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt

Это сканирование file.txt по строкам и соответствует чему угодно (.* ), которому предшествует строка "Auctions were started for, а затем другая ". Нам нужна опция grep -P, чтобы включить регулярные выражения PCRE (иначе мы не смогли бы использовать образы регулярного выражения (?<=...) и (?=...)] и его -o, чтобы печатать только согласованную часть строки (исключая обратные) вместо целой строки.

На втором этапе мы передаем вывод этой первой команды в эту команду sed:

sed -r 's/and |,|.com//g;y/ /\n/'

Это sed строка фактически содержит две команды: s/and |,|.com//g и y/ /\n/.

Во-первых, s/PATTERN/REPLACEMENT/ ищет регулярное выражение (расширенное регулярное выражение на самом деле из-за опции -r) and |,|.com, что означает and , , или .com. Затем он заменяет это ничем, поэтому эти шаблоны фактически удаляются из строки ввода. [F26] в конце позволяет глобальный поиск и замену вместо простой обработки первого совпадения в каждой строке.

Во-вторых, y/CHARACTERS/REPLACEMENTS/ переводит все символы в первом поле в соответствующие символы во втором поле , Здесь я использую это, чтобы просто преобразовать все оставшиеся пробелы в разрывы строк.

2
ответ дан 22 May 2018 в 22:24

Вы можете легко достичь этого с помощью комбинации grep, чтобы найти все строки в file.txt, содержащие текст «Аукционы были запущены для» и sed, чтобы извлекать только имена доменов без TLD и печатать по одной в строке :

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt | sed -r 's/and |,|.com//g;y/ /\n/'

Вот разбивка команды:

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt

Это сканирование file.txt по строкам и соответствует чему угодно (.* ), которому предшествует строка "Auctions were started for, а затем другая ". Нам нужна опция grep -P, чтобы включить регулярные выражения PCRE (иначе мы не смогли бы использовать образы регулярного выражения (?<=...) и (?=...)] и его -o, чтобы печатать только согласованную часть строки (исключая обратные) вместо целой строки.

На втором этапе мы передаем вывод этой первой команды в эту команду sed:

sed -r 's/and |,|.com//g;y/ /\n/'

Это sed строка фактически содержит две команды: s/and |,|.com//g и y/ /\n/.

Во-первых, s/PATTERN/REPLACEMENT/ ищет регулярное выражение (расширенное регулярное выражение на самом деле из-за опции -r) and |,|.com, что означает and , , или .com. Затем он заменяет это ничем, поэтому эти шаблоны фактически удаляются из строки ввода. [F26] в конце позволяет глобальный поиск и замену вместо простой обработки первого совпадения в каждой строке.

Во-вторых, y/CHARACTERS/REPLACEMENTS/ переводит все символы в первом поле в соответствующие символы во втором поле , Здесь я использую это, чтобы просто преобразовать все оставшиеся пробелы в разрывы строк.

2
ответ дан 18 July 2018 в 12:58

Вот несколько вариантов:

Подход KISS с использованием двух greps:

$ grep 'Auctions were started for' file | grep -o '\S*\.com' wantit1.com wantit2.com wantit3.com wantit4.com sidefun.com coffeetec.com lifeout.com new-fun-boys.com

Более элегантный:

$ perl -lne 'if (/"Auctions were started for (.*)"/) {print for split(/, | and /, $1)}' file wantit1.com wantit2.com wantit3.com wantit4.com sidefun.com coffeetec.com lifeout.com new-fun-boys.com
3
ответ дан 18 July 2018 в 12:58

Вы можете легко достичь этого с помощью комбинации grep, чтобы найти все строки в file.txt, содержащие текст «Аукционы были запущены для» и sed, чтобы извлекать только имена доменов без TLD и печатать по одной в строке :

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt | sed -r 's/and |,|.com//g;y/ /\n/'

Вот разбивка команды:

grep -Po '(?<="Auctions were started for ).*(?=")' file.txt

Это сканирование file.txt по строкам и соответствует чему угодно (.* ), которому предшествует строка "Auctions were started for, а затем другая ". Нам нужна опция grep -P, чтобы включить регулярные выражения PCRE (иначе мы не смогли бы использовать образы регулярного выражения (?<=...) и (?=...)] и его -o, чтобы печатать только согласованную часть строки (исключая обратные) вместо целой строки.

На втором этапе мы передаем вывод этой первой команды в эту команду sed:

sed -r 's/and |,|.com//g;y/ /\n/'

Это sed строка фактически содержит две команды: s/and |,|.com//g и y/ /\n/.

Во-первых, s/PATTERN/REPLACEMENT/ ищет регулярное выражение (расширенное регулярное выражение на самом деле из-за опции -r) and |,|.com, что означает and , , или .com. Затем он заменяет это ничем, поэтому эти шаблоны фактически удаляются из строки ввода. [F26] в конце позволяет глобальный поиск и замену вместо простой обработки первого совпадения в каждой строке.

Во-вторых, y/CHARACTERS/REPLACEMENTS/ переводит все символы в первом поле в соответствующие символы во втором поле , Здесь я использую это, чтобы просто преобразовать все оставшиеся пробелы в разрывы строк.

2
ответ дан 24 July 2018 в 20:04

Вот несколько вариантов:

Подход KISS с использованием двух greps:

$ grep 'Auctions were started for' file | grep -o '\S*\.com' wantit1.com wantit2.com wantit3.com wantit4.com sidefun.com coffeetec.com lifeout.com new-fun-boys.com

Более элегантный:

$ perl -lne 'if (/"Auctions were started for (.*)"/) {print for split(/, | and /, $1)}' file wantit1.com wantit2.com wantit3.com wantit4.com sidefun.com coffeetec.com lifeout.com new-fun-boys.com
3
ответ дан 24 July 2018 в 20:04

Другие вопросы по тегам:

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