Лучший способ разобрать эту конкретную строку с помощью awk / sed? - PullRequest
6 голосов
/ 31 января 2011

Мне нужно получить определенную строку версии из файла (назовите ее version.lst) и использовать ее для сравнения другой в сценарии оболочки. Например, ради, файл содержит строки, которые выглядят так:

V1.000 -- build date and other info here -- APP1
V1.000 -- build date and other info here -- APP2
V1.500 -- build date and other info here -- APP3

.. и так далее. Допустим, я пытаюсь получить первую версию (в данном случае V1.000) из APP1. Очевидно, что версии могут измениться, и я хочу, чтобы это было динамичным. То что у меня сейчас работает:

var = `cat version.lst | grep " -- APP1" | grep -Eo V[0-9].[0-9]{3}`

Pipe to grep получит строку, содержащую APP1, а вторая труба grep получит строку версии. Тем не менее, я слышал, что grep не способ сделать это, поэтому я хотел бы изучить лучший способ, используя awk или sed. Есть идеи? Я новичок в обоих и не нашел учебник достаточно легко, чтобы изучить его синтаксис. Они поддерживают egrep? Спасибо!

Ответы [ 3 ]

11 голосов
/ 31 января 2011

Попробуйте получить полную версию:

#!/bin/sh
app=APP1
var=$(awk -v "app=$app" '$NF == app {print $1}' version.lst)

или, чтобы получить только основной номер версии, последняя строка может быть:

var=$(awk -v "app=$app" '$NF == app {split($1,a,"."); print a[1]}' version.lst)

Использование sed для получения полной версии:

var=$(sed -n "/ $app\$/s/^\([^ ]*\).*/\1/p" version.lst)

или это, чтобы получить только основной номер версии:

var=$(sed -n "/ $app\$/s/^\([^.]*\).*/\1/p" version.lst)

Пояснения:

Вторая команда AWK:

  • -v "app=$app" - установить переменную AWK равной переменной оболочки
  • $NF == app - если последнее поле равно содержимому переменной (NF - номер поля, поэтому $NF - содержимое NF-го поля)
  • {split($1,a,".") - затем разбить первое поле на точку
  • print a[1] - и распечатать первую часть результата разбиения

Команды sed:

  • -n - не печатать никаких выходных данных, если не указано
  • "/ $app\$/ - для любой строки, которая заканчивается (\$) содержимым переменной оболочки $app (не то, чтобы двойные кавычки использовались для расширения переменной, и это хорошая идея, чтобы избежать второй знак доллара)
  • s/^\([^ ]*\).*/\1/p" - начиная с начала строки (^), захватывать \(\) последовательность символов, состоящую из непробельных символов ([^ ]) (или недоточек во второй версии) любое число (ноль или более *) и совпадение, но не захватывать все остальные символы в строке (.*), замените сопоставленный текст (в данном случае всю строку) на захваченную строку (номер версии) (\1 относится к первой (только в данном случае) группе захвата и распечатывает ее (p)
3 голосов
/ 31 января 2011

Если я правильно понял: egrep "APP1$" version.lst | awk '{print $1}'

1 голос
/ 31 января 2011
$ awk '/^V1\.00.* APP1$/{print $NF}' version.lst
APP1

Это регулярное выражение соответствует строкам, которые начинаются с "V1.00", за которым следует любое количество любых других символов, заканчивающихся на "APP1".Обратная косая черта в середине может быть очень важной - она ​​соответствует только «.», И поэтому исключает (возможно, поврежденные) строки, которые могут начинаться, скажем, с «V1a00».Пробел перед «APP1» исключает такие вещи, как «APP2_APP1».

«NF» - это автоматически генерируемая переменная, которая содержит номер поля во входной строке.Это также номер последнего поля, которое, как оказалось, вас интересует.

Есть несколько способов обрезки "V1".Вот один из способов, хотя мы с тобой, возможно, не говорим об одном и том же.

$ awk '/^V1\.00.* APP1$/{print substr($1, 1, index($1, ".") - 1), $NF}' version.lst
V1 APP1
...