У меня есть небольшой скрипт для извлечения определенных данных и небольшой очистки вывода. Это кажется слишком запутанным, и мне интересно, можно ли немного урезать сценарий.
Пример входного файла:
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
спасибо Сайрус Чарльз, я пытался объяснить, что сценарий / код не должен искать диапазоны номеров в области имени сервера.
Если это не всегда в каждой третьей строке, вы должны убедиться, что ваш образец ввода только иногда содержит лишние пробелы.
Ах, я вижу, как это произошло - если вы посмотрите на исходный пост на stackoverflow.com/revisions/…, то, как сайт его отрендерил, объединил разрывы строк, так что при редактировании я пытался вывести, где вы, В самом деле, хотели, чтобы они были, и ошибся; на самом деле вы хотели, чтобы источник выглядел эквивалентным соответствующему разделу stackoverflow.com/revisions/….
Ваш «дополнительный входной пример» по-прежнему должен быть связан с образцом выходных данных. Прямо сейчас мы не знаем, какой вывод должен быть в случае «два имени - одно число».
Новый дополнительный выход не совпадает с дополнительным входом - например, «дополнительный выход» содержит a1t0091 88
, но 88
на входе вообще отсутствует.
Подумайте о том, чтобы реализовать это в собственном 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
, он также имеет гораздо более короткое время запуска, поскольку не требуется никакого интерпретатора, кроме уже запущенной оболочки.
Видеть:
while read
.name=${name%%-*}
.(( ... ))
, используемый для числовых сравнений.это также, похоже, пропускает некоторые значения, возможно, из-за моей ошибки редактирования, упомянутой в комментариях выше
В самом деле, это важное различие (так что эти пустые строки содержат только иногда - гораздо более короткая / более простая ревизия для их обработки просто добавляет && read blank
в цикл while
и, таким образом, предполагает, что они всегда будут там). См. Этот ответ в отредактированном виде, работающий в ideone.com/5AhkTX
В awk это будет однострочный, в bash он такой огромный, вы уверены, что здесь есть что подумать?
@bipll, однострочный, если вы пишете его как нечитаемый awk. Если вы напишете его как хорошо отформатированный, прокомментированный awk (как я написал его как хорошо отформатированный, прокомментированный bash), он все равно будет разбит на несколько строк. Точно так же его можно было бы сделать однострочным и в bash за счет нечитаемости и невозможности обслуживания, но это ценит неправильные вещи. Краткость - это достоинство только тогда, когда она упрощает чтение и сопровождение кода.
@beastx см. ideone.com/ZPnz16 для расширенной версии этого (которая обрабатывает "пары", которые на самом деле имеют несколько имен перед числом) обработки вашего "расширенного примера ввода". (В будущем примеры должны пытаться следовать правилам минимальный воспроизводимый пример - самый короткий ввод, который реализует все необходимое поведение, предусмотренное заранее вопросом; это превращается в то, что мы называем «вопросом-хамелеоном», который постоянно редактируется после того, как правильный ответ превращается не удовлетворять истинные потребности ОП; здесь на них, как правило, неодобрительно смотрят).
(То, что сообщество awk ценит однострочники, которые жертвуют удобочитаемостью в пользу сохранения вертикальных пробелов - как будто это каким-то образом дорого обходится - я никогда не пойму. Разве эти многострочные версии скриптов awk
, предоставленные Сайрусом и Каракфой не легче понять, чем оригиналы? ).
@charles Я не могу заставить ваше решение работать. Он просто показывает пустой экран.
Да, форматирование и тому подобное для задания такого вопроса было для меня новым опытом, и запрос на один лайнер больше подходит для возможного будущего автоматического использования, но в настоящее время работает полный скрипт или однострочный.
@beastx, я предоставил ссылки на ideone только для того, чтобы вы могли на самом деле вижу, как работает код; см. «stdout» в нижней части страницы - это результат кода, когда копия bash, запущенная ideone.com, вызвала его. Если у вас есть вопросы о том, как сделать автоматическое использование многострочного скрипта, не стесняйтесь задавать такой вопрос, если вы не можете найти его уже в базе знаний - буквально нет случая, когда вы можете использовать однострочный скрипт, но не могу использовать скрипт.
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
Извините, не используется для правильного редактирования, во входном файле есть лишние пробелы, обычно в каждой третьей строке, но не всегда, поэтому это, похоже, нарушает ваш код
Формат вашего входного файла сильно изменился, обновленный сценарий зависит от структуры записи, в противном случае, если файл не структурирован последовательно, вам нужно вернуться к сопоставлению с образцом. Вы не упомянули, что происходит, когда две текстовые строки сопровождаются одним числом, как в вашем последнем примере.
Карафка, да, если посмотреть глубже во входной файл вместе с уроками, полученными при задании подобного вопроса, начальные квесты немного изменились. Но этот единственный лайнер, кажется, движется в правильном направлении.
С 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 не лучший инструмент для этой задачи, но я получаю ожидаемый результат. Возможно, вы сможете объяснить это в комментариях.
Мое предположение (как человека, получившего отрицательный голос примерно в то же время) состоит в том, что этот человек давал ответы, которые они считали слишком сложными или трудными для читателей, поскольку вопрос требовал ясного или простого решения. Конечно, если, который действительно был их возражением, «трудно понять» можно противопоставить, добавив комментарии, краткое описание функции, ссылки и т. д. Я попытался отредактировать свой ответ с этой целью.
«Игнорировать числа в строках имени сервера» здесь не имеет смысла - в вашем примере вывода все еще есть числа. Пожалуйста, убедитесь, что текстовое описание и пример соответствуют друг другу.