Извлечение только определенных нескольких шаблонов из файла

I есть следующий файл:

 $less dummyKeyAndValue.txt
   apiKey=key1;some_other_data;term=abc
   apiKey=key2;some_other_data;some_other_data;term=def
   term=pqr;some_other_data;apiKey=key1
   apiKey=key3;some_other_data;term=def

Я хочу, чтобы результат был следующим:

 $less dummyNewFile.txt
   apiKey=key1 term=abc
   apiKey=key2 term=def
   apiKey=key1 term=pqr
   apiKey=key3 term=def

В основном я хочу извлечь 'apiKey' и 'term' из файла dummyKeyAndValue.txt, они оба могут появляться в файле в разном порядке. Я попытался выполнить следующее. команда:

   $cat dummyKeyAndValue.txt | tee >(egrep -o 'apiKey=[a-zA-Z0-9]+')  |   
   egrep -o 'term=[a-zA-Z]+' | less

Я получаю вывод как:

     term=abc
     term=def
     term=pqr
     term=def

Может ли кто-нибудь помочь мне с командой для получения желаемого результата?

0
03.01.2017, 01:43
3 ответа

В качестве альтернативы очень эффективное, но немного более сложное решение

sed 'G;s/;/\n/' | awk -F= '
$1~/apiKey/ {key=$2}
$1~/term/ {term=$2}
/^$/ {printf("  apiKey=%s term=%s\n", key, term)
      key=""
      term=""}'

Сначала sed используется для двух вещей: команда «G» эффективно добавляет открытую строку после каждого «набора записей», а во-вторых, «заменяет» команда ( s /; / \ n / ) эффективно расширяет каждый набор записей до одной на строку, заменяя каждый ; символом новой строки. Что выходит из sed, так это пары ключ-значение, по одной на строку, с открытой строкой, обозначающей конец каждой записи.

Затем awk нужно только просмотреть первое поле, чтобы найти интересующие вас атрибуты, и второе поле для значения, что устраняет необходимость в index и substr. Как только awk встречает «открытую строку», он печатает найденные значения. В целях устойчивости вы можете «очистить» значения в конце каждой записи. Обратите внимание на использование -F = для указания awk разбить строку на поля на основе знака = .

$ 1 ~ /.../ означает: «Когда первое поле соответствует значению /.../

, оно затем присваивает значение переменной (ключу или термину)

/ ^ $ / означает «когда awk встречает открытую строку»

0
28.01.2020, 02:47

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

/tmp$ cat a.awk
{
   keypart=substr($0, index($0, "apiKey=")+7)
   keyvalue=substr(keypart, 1, index(keypart, ";")-1)

   termpart=substr($0, index($0, "term=")+5)
   termvalue=substr(termpart, 1, index(termpart, ";")-1)

# If the attribute is last on the input line there will be no ; to mark the end so use the whole part
   if(keyvalue=="") {keyvalue=keypart}
   if(termvalue=="") {termvalue=termpart}
   printf ("  apikey=%s term=%s\n", keyvalue, termvalue)
}

Сценарий Awk (названный выше a.awk, но можно использовать любое имя файла в смысле makse) можно использовать следующим образом:

awk -f a.awk inputfile

Как вы можете видеть, я обрабатываю случай поля ввода, которое заканчивается в конце строка специально с оператором if для каждого. Я бы улучшил этот скрипт следующим образом, чтобы автоматически обрабатывать эти случаи:

/tmp$ cat a.awk  
{
   LINE=$0 ";"

   keypart=substr(LINE, index(LINE, "apiKey=")+7)
   keyvalue=substr(keypart, 1, index(keypart, ";")-1)

   termpart=substr(LINE, index(LINE, "term=")+5)
   termvalue=substr(termpart, 1, index(termpart, ";")-1)

   printf ("  apikey=%s term=%s\n", keyvalue, termvalue)
}

Польза от этого становится яснее, когда вы добавляете больше случаев!

1
28.01.2020, 02:47

Вероятно не очень эффективно, но если вы хотите продолжить свой подход «двух greps», вы можете сделать это, используя paste :

$ paste <(grep -o 'apiKey=[^;]*' dummyKeyAndValue.txt) <(grep -o 'term=[^;]*' dummyKeyAndValue.txt)
apiKey=key1     term=abc
apiKey=key2     term=def
apiKey=key1     term=pqr
apiKey=key3     term=def

Или подход KISS, используя GNU sed :

sed -nE -e 's/(apiKey=[^;]*).*(term=[^;]*)/\1 \2/p' \
  -e 's/(term=[^;]*).*(apiKey=[^;]*)/\2 \1/p' dummyKeyAndValue.txt
0
28.01.2020, 02:47

Теги

Похожие вопросы