2010-09-07 5 views
0

У меня есть вкладка с разделителем каретки (ключ = значение) и хотелось бы извлечь из нее несколько токенов, представляющих интерес.Извлечение нескольких частей строки с использованием bash

Например: Учитывая следующие входные

$ echo -e "1=A00^35=D^150=1^33=1\n1=B000^35=D^150=2^33=2" 
1=A00^35=D^22=101^150=1^33=1 
1=B000^35=D^22=101^150=2^33=2  

Я хотел бы следующий вывод

35=D^150=1^ 
35=D^150=2^ 

Я попытался следующий

$ echo -e "1=A00^35=D^150=1^33=1\n1=B000^35=D^150=2^33=2"|egrep -o "35=[^/^]*\^|150=[^/^]*\^" 
35=D^ 
150=1^ 
35=D^ 
150=2^ 

Моя проблема в том, что задать расширенное возвращает каждый матч на отдельной строке. Можно ли получить одну линию вывода для одной строки ввода? Обратите внимание, что из-за ограничений большего скрипта я не могу просто сделать слепую замену всех \ n символов в выходе.

Благодарим за любые предложения. Этот сценарий предназначен для bash 3.2.25. Любые альтернативы egrep приветствуются. Обратите внимание, что токены, представляющие интерес (35 и 150), могут измениться, и я уже создаю шаблон egrep в скрипте. Следовательно, один вкладыш (если это возможно) было бы здорово

ответ

0

Чтобы избавиться от символа новой строки, вы можете просто повторить его еще раз:

$ echo $(echo "1=A00^35=D^150=1^33=1"|egrep -o "35=[^/^]*\^|150=[^/^]*\^") 
35=D^ 150=1^ 

Если это не устраивает (я думаю, что это может дать вам одну линию весь входной файл), вы можете использовать awk:

pax> echo ' 
1=A00^35=D^150=1^33=1 
1=a00^35=d^157=11^33=11 
' | awk -vLIST=35,150 -F^ ' { 
     sep = ""; 
     split (LIST, srch, ","); 
     for (i = 1; i <= NF; i++) { 
      for (idx in srch) { 
       split ($i, arr, "="); 
       if (arr[1] == srch[idx]) { 
        printf sep "" arr[1] "=" arr[2]; 
        sep = "^"; 
       } 
      } 
     } 
     if (sep != "") { 
      print sep; 
     } 
    }' 
35=D^150=1^ 
35=d^ 

 

pax> echo ' 
1=A00^35=D^150=1^33=1 
1=a00^35=d^157=11^33=11 
' | awk -vLIST=1,33 -F^ ' { 
     sep = ""; 
     split (LIST, srch, ","); 
     for (i = 1; i <= NF; i++) { 
      for (idx in srch) { 
       split ($i, arr, "="); 
       if (arr[1] == srch[idx]) { 
        printf sep "" arr[1] "=" arr[2]; 
        sep = "^"; 
       } 
      } 
     } 
     if (sep != "") { 
      print sep; 
     } 
    }' 
1=A00^33=1^ 
1=a00^33=11^ 

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


А вот версия однострочник :-)

echo '1=A00^35=D^150=1^33=1 
     1=a00^35=d^157=11^33=11 
     ' | awk -vLST=1,33 -F^ '{s="";split(LST,k,",");for(i=1;i<=NF;i++){for(j in k){split($i,arr,"=");if(arr[1]==k[j]){printf s""arr[1]"="arr[2];s="^";}}}if(s!=""){print s;}}' 
+0

Thanks для вашего ответа Pax. Я отредактировал вопрос, чтобы лучше описать мою проблему. Решение awk было бы удивительным, за исключением того, что мне не всегда будут нужны 35 и 150. Я уже создаю regex egrep, и генерация всего заявления awk кажется немного грубой силой. – Dave

+0

@Dave, см. Обновление. Сам сценарий не изменяется, поскольку теперь вы просто представляете список интересующих токенов. Единственное, что вам нужно генерировать динамически, это бит '-vLIST ='. – paxdiablo

+0

Спасибо, миллион! – Dave

1

У вас есть два варианта. Вариант 1, чтобы изменить "белый пробел" и использовать set --:

OFS=$IFS 
IFS="^ " 
set -- 1=A00^35=D^150=1^33=1 # No quotes here!! 
IFS="$OFS" 

Теперь у вас есть свои ценности в $1, $2 и т.д.

Или вы можете использовать массив:

tmp=$(echo "1=A00^35=D^150=1^33=1" | sed -e 's:\([0-9]\+\)=: [\1]=:g' -e 's:\^ : :g') 
eval value=($tmp) 
echo "35=${value[35]}^150=${value[150]}" 
0

предоставил файл 'in', содержащий ваши строки:

$ for i in $(cut -d^ -f2,3 < in);do echo $i^;done 
35=D^150=1^ 
35=D^150=2^ 
Смежные вопросы