2013-04-16 3 views
2

В настоящее время у меня есть команда в скрипте Баш, что отбирает для данной строки в текстовом файле и печатает номера строк только с использованием СЭД ...Распаковка минимум и максимум от номера строки Grep

grep -n "<string>" file.txt | sed -n 's/^\([0-9]*\).*/\1/p' 

grep может найти несколько совпадений и, таким образом, распечатать несколько номеров строк. Из вывода этой команды я хотел бы извлечь минимальное и максимальное значения и назначить их соответствующим переменным bash. Как я могу лучше всего изменить существующую команду или добавить новые команды для этого? Если использование awk или sed будет необходимо, я предпочитаю использовать sed. Благодаря!

ответ

3

Вы можете получить минимум и максимум с этим:

grep -n "<string>" input | sed -n -e 's/^\([0-9]*\).*/\1/' -e '1p;$p' 

Вы также можете прочитать их в массив:

F=($(grep -n "<string>" input | sed -n -e 's/^\([0-9]*\).*/\1/' -e '1p;$p')) 
echo ${F[0]} # min 
echo ${F[1]} # max 
+0

Grep get это имя от 'sed -n g/re/p'. Вы должны быть в состоянии объединить все в sed вместо того, чтобы передавать выходные данные grep в sed. –

+0

Но номер строки номера усложняет это. Похоже, вам нужна серия sed-sed для этого. – perreal

2
grep -n "<string>" file.txt | sed -n -e '1s/^\([0-9]*\).*/\1/p' -e '$s/^\([0-9]*\).*/\1/p' 
+0

Спасибо! Ваш ответ работает. В идеале я хотел бы распечатать исключительно мин или максимум. Есть ли способ для вашей команды печатать только минимум или только максимум? Или вы предложите такое же решение, которое предлагает perreal ниже? – user2150250

1
grep .... |awk -F: '!f{print $1;f=1} END{print $1}' 
+0

Это может быть немного легче понять: '... | awk -F: 'NR == 1 {print $ 1} END {print $ 1}' ' –

+0

@AnsgarWiechers ha yes! Я просто подумал о логическом ... «забыл» «NR» - номер строки. :) – Kent

+0

также 'grep' не нужен! Построил grep в awk. Сохраните процесс для тропических лесов! ;) – TrueY

1

Вот как я это сделать , поскольку grep -n 'pattern' file печатает выходные данные в формате line number:line contents ...

minval=$(grep -n '<string>' input | cut -d':' -f1 | sort -n | head -1) 
    maxval=$(grep -n '<string>' input | cut -d':' -f1 | sort -n | tail -1) 

команда cut -d':' -f1 разделяет grep выход вокруг толстой кишки и вытаскивает только первое поле (номера строки), sort -n сортирует номера числовые строки в порядке возрастания (что они уже были бы в, но это хорошая практика убедитесь в этом), затем head -1 и tail -1 удалите первое и последнее значение в отсортированном списке соответственно, то есть минимальное и максимальное значения, и назначьте их переменным $minval и $maxval соответственно.

Надеюсь, это поможет!

Редактировать: Оказывается, вы не можете сделать это так, как это было изначально, поскольку эхо из списка значений, разделенных новой строкой, по-видимому, объединяет их в одну строку.

+0

Мне нравится это решение, но оно, кажется, дает мне ошибку: 'head: не может открыть '96' для чтения: Нет такой файл или каталог head: не может открыть '100' для чтения: нет такого файла или каталога'. Конечно, цифры находятся в контексте моего входного файла, но, похоже, это не нравится «head» или «tail». Какие-либо предложения? – user2150250

+0

Он также говорит, что «tail: option используется в недопустимом контексте - 1' – user2150250

+0

Оказывается, вы не можете сделать это так, как я его первоначально использовал (используя эту третью переменную), так как, когда вы эхом, он помещает все значения в одну строку (что означает, что голова и хвост не работают должным образом). Код должен там работать нормально – CaffeineConnoisseur

0

Это можно сделать одним способом. Например:

awk '/expression/{if(!n)print NR;n=NR} END {print n}' file.txt 

Затем вы можете назначить массив (как предлагалось в perreal). Или Вы можете изменить этот сценарий и назначить varables с помощью Eval

eval $(awk '/expression/{if(!n)print "A="NR;n=NR} END {print "B="n}' file.txt) 
echo $A 
echo $B 

Output (file.txt содержит три строки expression)

1 
3 
Смежные вопросы