LINUX.ORG.RU

grep'нуть надо

 , , ,


1

1

вот есть например такой файл:

40:45:DA:A5:DF:70 43
02:93:E0:94:9D:FA 10
B8:03:05:95:53:4E 10
нужно проверить превышает ли второе значение 25, если превышает, то записать этот mac в другой файл

прошу помощи



Последнее исправление: adminlinwin (всего исправлений: 4)

Ответ на: комментарий от pavelshuvalov

Для подобного придумали специальный язык и назвали его awk

$ awk '{if ($2 > 25) print $0}' 1.txt > 25.txt
$ cat 1.txt
40:45:DA:A5:DF:70 43
02:93:E0:94:9D:FA 10
B8:03:05:95:53:4E 10
$ cat 25.txt
40:45:DA:A5:DF:70 43

justAmoment ★★★★★
()
Последнее исправление: justAmoment (всего исправлений: 1)

если бы не анончик, то рак уже давно бы поразил лор.

anonymous
()

Про какое второе значение речь? Вторую позицию в строке или второй октет в mac? Могут ли в файле быть пробелы до mac-адреса? Второе число в какой системе счисления? Могут ли быть другие значения кроме MAC и числа?

Если нет, то можно примерно так:

grep -E '\s([^12]|2[^0-5]|...)' your.file.txt

Xenius ★★★★★
()
Последнее исправление: Xenius (всего исправлений: 1)
Ответ на: комментарий от justAmoment

Для подобного придумали специальный язык и назвали его awk

awk тут избыточен, более чем достаточно простого grep

Xenius ★★★★★
()
Ответ на: комментарий от pavelshuvalov

Но там уже написали выше, что лучше использовать awk или grep. Я бы даже сказал, что лучше awk.

pavelshuvalov
()
Ответ на: комментарий от Xenius

awk тут избыточен, более чем достаточно простого grep

Но ведь в ПП есть задача сравнить несколько чисел, и в случае с awk числа удаётся сравнить арифметически, а в случае с grep - как строки, через регулярные выражения.

pavelshuvalov
()
Ответ на: комментарий от anonymous

awk '$2 > 25 { print $1 }' input.txt > output.txt

anonymous
()
Ответ на: комментарий от Xenius

Ага, а как только появляется доп. требование для обработки, это превращается в такую write-only лапшу, а в awk всё чинно, стильно, благородно.

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

$ awk '{print $0 > int($2/10)"0-"int($2/10)"9.txt"}' source.txt
$ awk '{print FILENAME "  <--  " $0}' *
00-09.txt  <--  RANDOM-MAC 5
10-19.txt  <--  02:93:E0:94:9D:FA 10
10-19.txt  <--  B8:03:05:95:53:4E 10
40-49.txt  <--  40:45:DA:A5:DF:70 43
source.txt  <--  40:45:DA:A5:DF:70 43
source.txt  <--  02:93:E0:94:9D:FA 10
source.txt  <--  B8:03:05:95:53:4E 10
source.txt  <--  RANDOM-MAC 5

justAmoment ★★★★★
()
Ответ на: комментарий от Xenius

Да нафиг тут grep и awk не нужен. Просто тут никто не знает sh, особенно pavelshuvalov.

#!/bin/sh
while read mac value; do
        [ $value -gt 25 ] && echo "$mac $value > 25"
done < "$1"
Работает даже в ash.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от justAmoment

Модернизации & Инновации

$ awk '{d=sprintf("%04d",int($2/10)); print $0 > d"0-"d"9.txt"}' source.txt
$ awk '{print FILENAME "  <--  " $0}' *
00000-00009.txt  <--  RANDOM-MAC1 5
00010-00019.txt  <--  02:93:E0:94:9D:FA 10
00010-00019.txt  <--  B8:03:05:95:53:4E 10
00040-00049.txt  <--  40:45:DA:A5:DF:70 43
00500-00509.txt  <--  RANDOM-MAC2 505
04400-04409.txt  <--  RANDOM-MAC3 4400
source.txt  <--  40:45:DA:A5:DF:70 43
source.txt  <--  02:93:E0:94:9D:FA 10
source.txt  <--  B8:03:05:95:53:4E 10
source.txt  <--  RANDOM-MAC1 5
source.txt  <--  RANDOM-MAC2 505
source.txt  <--  RANDOM-MAC3 4400
justAmoment ★★★★★
()
Ответ на: комментарий от justAmoment

Ага, а как только появляется доп. требование для обработки, это превращается в такую write-only лапшу

А кто мешает пользоваться наиболее подходящим инструментом, когда это разумно? Например, задача точно как сформулирована — берём grep. Задача усложняется — переходим на awk.

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

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

vodz ★★★★★
()
Ответ на: комментарий от justAmoment

Для подобного придумали специальный язык и назвали его awk

+1

anonymous
()
Ответ на: комментарий от anonymous

http://xyproblem.info/

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

vodz ★★★★★
()
Ответ на: комментарий от vodz

Молодец, что знаешь sh. Теперь:

  • В ПП есть требование сравнить второе число с 25 и записать в файл сравниваемое число при выполнении сравнения
  • Как - не имеет значения; однако
  • Решение средствами шелла - на каждый чих создавать процесс: парсинг, запись в файл (тут не совсем создание процесса, но дёргание fopen - есть в каждой итерации при выполнении условия). Это не плохо, так работает шелл - он запилен под работу с процессами.
    • POSIX sh или bash - вообще плевать.
  • Средствами grep достаются значения, но сравниваются они как строки. Тем не менее, процесс создаётся только один раз и fopen - тоже один.
  • Средствами awk достаются​ значения и сравниваются арифметически. exec/fopen - всё ещё только один вызов.

Вот и получается, что нужно использовать именно awk.

pavelshuvalov
()
Ответ на: комментарий от anonymous

Здесь не про это. Здесь мы выбираем правильный инструмент для решения проблемы, а не определяемся с самой проблемой.

pavelshuvalov
()
Ответ на: комментарий от pavelshuvalov

Ну зачем вы продолжаете показываеть своё незнание шелла? fopen можно делать ровно раз:: exec 3>file перед циклом, а к echo дописать 1>&3 Никакого дополнительного процесса в указанном скрипте нет. И shell не работает с stdio, потому и не fopen, а open

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 3)
Ответ на: комментарий от pavelshuvalov

Да если тупо stdout не нужен, то можно и к done приписать > outfile, это то то точно первым делом напрашивается по аналогии с < infile

vodz ★★★★★
()
Ответ на: комментарий от pavelshuvalov

На тебе sh, и больше такие глупости не пиши.

while IFS=: read -r first second rest; do
    value=0x$second
    cmp=$(( value > 25 ))
    [ "$cmp" = 1 ] && echo "$first:$second:$rest"
done < "$1" > "$2"

на каждый чих создавать процесс

Это неправда. И приведённый скрипт, и мой, форкаются ровно ноль

fopen

Мде.

shdown
()
Ответ на: комментарий от shdown

На тебе sh

Спасибо, не нужно.

Средствами awk достаются​ значения и сравниваются арифметически.

ТС всё правильно сделал, что выбрал awk.

pavelshuvalov
()
Ответ на: комментарий от pavelshuvalov

Средствами awk достаются​ значения и сравниваются арифметически.

Кого ты цитируешь? Где в моём посте awk? Иди лечись.

shdown
()
Ответ на: комментарий от shdown

Для вашей копилки знаний sh: cmp у вас либо 0 либо 1, потому «» не обязательны, а только тормозят; операция '=' - строковая, она медленнее, чем численная -gt, да и сравнивать разнеся на две строки — запутывать читателя. Итого внутренность цикла будет:

value=$((0x$second))

[ $value -gt 25 ] && ...

А вообще, судя по тому, какое ТС выбрал решение, задача была другая, сравнивать второе поле после пробела :)

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от adminlinwin

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

vodz ★★★★★
()
Ответ на: комментарий от vodz

медленнее

«» не обязательны, а только тормозят

Все реализации sh, про которые мне известно, на каждую строку вообще malloc делают, а он, значит, кавычки оптимизирует — тормозят они у него, видите ли.

Итого внутренность цикла будет:

А чё не

[ $((0x$second>25)) ]&&…
? Ну там, без пробельчиков, чтоб не тормозило, лол:
$ ( echo second=af; repeat 200000 echo '[ $((0x$second>25)) = 1 ]&&echo 1' ) > foo.sh; time sh foo.sh >/dev/null

real	2.09s
user	2.03s
sys	0.06s
$ ( echo second=af; repeat 200000 echo 'v=$((0x$second));[ $v -gt 25 ]&&echo 1' ) > foo.sh; time sh foo.sh >/dev/null

real	2.89s
user	2.80s
sys	0.08s

shdown
()
Ответ на: комментарий от shdown

Все реализации sh, про которые мне известно, на каждую строку вообще malloc делают

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

А чё не

Как вы предсказуемы :) Так читается хуже в другую сторону.

Накой вообще у вас это желание сравнивать с единицей, если по условию надо тоже сравнивать, но с другим числом? Да если б не перевод hex-dec, арифметика вообще бы не нужна была.

Ну там, без пробельчиков,

Да запросто:

let $((0x$second>25)) && echo ...

vodz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.