Как можно более аккуратно реализовать скрипт "grep | sed | awk", объединяющий пары строк?

У меня есть небольшой скрипт для извлечения определенных данных и небольшой очистки вывода. Это кажется слишком запутанным, и мне интересно, можно ли немного урезать сценарий.


  • Входной файл состоит из пар строк - имен, за которыми следуют числа.
  • Пары строк, числовое значение которых не находится в диапазоне от 80 до 199, следует отбрасывать.
  • Иногда, но не всегда, парам могут предшествовать или следовать пустые строки, которые следует игнорировать.

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

al12t5682-heapmemusage-latest.log
38

al12t5683-heapmemusage-latest.log
88
al12t5684-heapmemusage-latest.log
100
al12t5685-heapmemusage-latest.log
0

al12t5686-heapmemusage-latest.log
91

Пример / желаемый результат:

al12t5683 88
al12t5684 100
al12t5686 91

Текущий сценарий:

grep --no-group-separator -PxB1 '([8,9][0-9]|[1][0-9][0-9])' inputfile.txt \
  | sed 's/-heapmemusage-latest.log//' \
  | awk '{$1=$1;printf("%s ",$0)};NR%2==0{print ""}'

Пример дополнительного ввода

al14672-heapmemusage-latest.log
38

al14671-heapmemusage-latest.log
5

g4t5534-heapmemusage-latest.log
100

al1t0000-heapmemusage-latest.log
0
al1t5535-heapmemusage-latest.log
al1t4676-heapmemusage-latest.log
127

al1t4674-heapmemusage-latest.log
53

A1t5540-heapmemusage-latest.log
54

G4t9981-heapmemusage-latest.log
45

al1c4678-heapmemusage-latest.log
81

B4t8830-heapmemusage-latest.log
76

a1t0091-heapmemusage-latest.log
88

al1t4684-heapmemusage-latest.log
91

Дополнительный пример ожидаемого результата:

g4t5534 100
al1t4676 127
al1c4678 81
a1t0091 88
al1t4684 91

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

Charles Duffy 01.05.2018 17:49

спасибо Сайрус Чарльз, я пытался объяснить, что сценарий / код не должен искать диапазоны номеров в области имени сервера.

beastx 02.05.2018 09:55

Если это не всегда в каждой третьей строке, вы должны убедиться, что ваш образец ввода только иногда содержит лишние пробелы.

Charles Duffy 02.05.2018 15:55

Ах, я вижу, как это произошло - если вы посмотрите на исходный пост на stackoverflow.com/revisions/…, то, как сайт его отрендерил, объединил разрывы строк, так что при редактировании я пытался вывести, где вы, В самом деле, хотели, чтобы они были, и ошибся; на самом деле вы хотели, чтобы источник выглядел эквивалентным соответствующему разделу stackoverflow.com/revisions/….

Charles Duffy 02.05.2018 16:09

Ваш «дополнительный входной пример» по-прежнему должен быть связан с образцом выходных данных. Прямо сейчас мы не знаем, какой вывод должен быть в случае «два имени - одно число».

Charles Duffy 03.05.2018 13:39

Новый дополнительный выход не совпадает с дополнительным входом - например, «дополнительный выход» содержит a1t0091 88, но 88 на входе вообще отсутствует.

Charles Duffy 03.05.2018 16:55
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
128
4

Ответы 4

Подумайте о том, чтобы реализовать это в собственном bash, как показано ниже (которое можно увидеть в вашем примере ввода, включая периодически присутствующие пустые строки, в http://ideone.com/Qtfmrr):

#!/bin/bash
name=; number=
while IFS= read -r line; do
  [[ $line ]] || continue                       # skip blank lines
  [[ -z $name ]] && { name=$line; continue; }   # first non-blank line becomes name
  number=$line                                  # second one becomes number
  if (( number >= 80 && number < 200 )); then
    name=${name%%-*}                            # prune everything after first "-"
    printf '%s %s\n' "$name" "$number"          # emit our output
  fi
  name=; number=                                # clear the variables
done <inputfile.txt

Вышеупомянутое вообще не использует никаких внешних команд - поэтому, хотя он может быть медленнее обрабатывать большие входные данные, чем хорошо реализованный сценарий awk или perl, он также имеет гораздо более короткое время запуска, поскольку не требуется никакого интерпретатора, кроме уже запущенной оболочки.

Видеть:

это также, похоже, пропускает некоторые значения, возможно, из-за моей ошибки редактирования, упомянутой в комментариях выше

beastx 02.05.2018 10:00

В самом деле, это важное различие (так что эти пустые строки содержат только иногда - гораздо более короткая / более простая ревизия для их обработки просто добавляет && read blank в цикл while и, таким образом, предполагает, что они всегда будут там). См. Этот ответ в отредактированном виде, работающий в ideone.com/5AhkTX

Charles Duffy 02.05.2018 16:11

В awk это будет однострочный, в bash он такой огромный, вы уверены, что здесь есть что подумать?

bipll 03.05.2018 07:44

@bipll, однострочный, если вы пишете его как нечитаемый awk. Если вы напишете его как хорошо отформатированный, прокомментированный awk (как я написал его как хорошо отформатированный, прокомментированный bash), он все равно будет разбит на несколько строк. Точно так же его можно было бы сделать однострочным и в bash за счет нечитаемости и невозможности обслуживания, но это ценит неправильные вещи. Краткость - это достоинство только тогда, когда она упрощает чтение и сопровождение кода.

Charles Duffy 03.05.2018 13:33

@beastx см. ideone.com/ZPnz16 для расширенной версии этого (которая обрабатывает "пары", которые на самом деле имеют несколько имен перед числом) обработки вашего "расширенного примера ввода". (В будущем примеры должны пытаться следовать правилам минимальный воспроизводимый пример - самый короткий ввод, который реализует все необходимое поведение, предусмотренное заранее вопросом; это превращается в то, что мы называем «вопросом-хамелеоном», который постоянно редактируется после того, как правильный ответ превращается не удовлетворять истинные потребности ОП; здесь на них, как правило, неодобрительно смотрят).

Charles Duffy 03.05.2018 13:48

(То, что сообщество awk ценит однострочники, которые жертвуют удобочитаемостью в пользу сохранения вертикальных пробелов - как будто это каким-то образом дорого обходится - я никогда не пойму. Разве эти многострочные версии скриптов awk, предоставленные Сайрусом и Каракфой не легче понять, чем оригиналы? ).

Charles Duffy 03.05.2018 14:06

@charles Я не могу заставить ваше решение работать. Он просто показывает пустой экран.

beastx 03.05.2018 15:10

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

beastx 03.05.2018 15:12

@beastx, я предоставил ссылки на ideone только для того, чтобы вы могли на самом деле вижу, как работает код; см. «stdout» в нижней части страницы - это результат кода, когда копия bash, запущенная ideone.com, вызвала его. Если у вас есть вопросы о том, как сделать автоматическое использование многострочного скрипта, не стесняйтесь задавать такой вопрос, если вы не можете найти его уже в базе знаний - буквально нет случая, когда вы можете использовать однострочный скрипт, но не могу использовать скрипт.

Charles Duffy 03.05.2018 16:50
perl -nle's/-.*//; $n=<>; print "$_ $n" if 80<=$n && $n<=199' inputfile.txt

другой awk

$ awk -F- 'NR%2{p=$1; next} 80<=$1 && $1<=199 {print p,$1}' file

al12t5683 88
al12t5684 100
al12t5686 91

ОБНОВИТЬ

для разделителя записи пустой строки

$ awk -v RS= '80<=$2 && $2<=199{sub(/-.*/,"",$1); print}' file

al12t5683 88
al12t5684 100
al12t5686 91

Извините, не используется для правильного редактирования, во входном файле есть лишние пробелы, обычно в каждой третьей строке, но не всегда, поэтому это, похоже, нарушает ваш код

beastx 02.05.2018 09:57

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

karakfa 03.05.2018 13:00

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

beastx 03.05.2018 13:03

С GNU sed

sed -E '
N
/\n[8-9][0-9]$/bA
/\n1[0-9]{2}$/!d
:A
s/([^-]*).*\n([0-9]+$)/\1 \2/
' infile

@Anonymous Downvoter Конечно, sed не лучший инструмент для этой задачи, но я получаю ожидаемый результат. Возможно, вы сможете объяснить это в комментариях.

ctac_ 01.05.2018 19:06

Мое предположение (как человека, получившего отрицательный голос примерно в то же время) состоит в том, что этот человек давал ответы, которые они считали слишком сложными или трудными для читателей, поскольку вопрос требовал ясного или простого решения. Конечно, если, который действительно был их возражением, «трудно понять» можно противопоставить, добавив комментарии, краткое описание функции, ссылки и т. д. Я попытался отредактировать свой ответ с этой целью.

Charles Duffy 01.05.2018 22:11

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