Grep для набора строк от $START до $END И содержащий совпадение в $MIDDLE

Grep для набора строк от $START до $END И содержащий совпадение в $MIDDLE

Grep/Awk/Sed для набора строк от «0010|» до «0070|» И содержащий совпадение в $PH_NO

Ниже приведен пример данных. Мне нужно выполнить grep для номера телефона, который присутствует в поле 0012, и соответствующих полных записей клиентов, строк от 0010 до 0070. Один файл данных может содержать две или три записи клиентов с одинаковым номером телефона, и мне нужно получить их все.

0010|Kumar||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|RAM||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 333| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|Joe||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|

Примечание: Я работаю на сервере AIX с ksh.

решение1

Итак, вам нужна вся запись от 0010 до 0070, если номер PH совпадает $PH_NO"? Тогда этот sedоднострочник сработает:

sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
  • /^0010/,/^0070/Hдля добавления одной записи с 0010 по 0070 в область удержания
  • /^0010/h0010 не должен добавляться, а должен начинать новую запись, поэтому скопируйте его в область удержания
  • /^0070/! dникакой дальнейшей обработки или вывода, если только это не элемент 0070
  • x;/|$PH_NO| PH Number/! d"поменяйте местами пробелы так, чтобы вся запись теперь находилась в пространстве шаблона, и удалите ее, если она не содержит указанного числа.

решение2

for r in `grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed 's/,[0-9]\+,/,/g'`; do sed -n "$r"p CUSTOMER_FILE; echo; done

149 196 222в команде выше — номер телефона клиента. Измените его на номер телефона, который вы хотите узнать.

CUSTOMER_FILEэто файл, который вы хотите найти. Измените его на имя вашего файла.

Вы также можете поместить код в скрипт bash, и заменить 149 196 222на $1и заменить CUSTOMER_FILEна $2. Скажем, find-customer.sh, затем вы можете выполнить скрипт следующим образом

./find-customer.sh '149 196 222' your-file-name

Предварительные условия этого фрагмента кода:

  1. Bash, среда GNU (GNU grep, GNU sed)
  2. Ваш файл должен соответствовать формату, как показано ниже. 0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file>


ОБНОВЛЯТЬ

Это высокопроизводительная версия. (По крайней мере, выше, чем оригинальная версия выше. Цикл for вообще не задействован.)

grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed -r 's|([0-9]+),[0-9]+,([0-9]+)|\1,\2p;\2a|g' | sed -n -f - CUSTOMER_FILE


ОБНОВЛЕНИЕ для AIX

Так как автор вопроса работает на AIX. Команда grep на AIX не поддерживает параметры контекста -A, -B, -C.

В Интернете есть множество реализаций "cgrep" (context grep) для решения этой проблемы (для имитации контекстной опции GNU grep). Но большинство из них не могут дать такой же вывод, как GNU grep. Только одна, которую я нашел, наиболее близка к контекстной опции GNU grep. Ссылкаhttps://stackoverflow.com/questions/1685678/advanced-grep-unix/1685782#1685782

Я внес некоторые необходимые изменения для этого случая.

#!/bin/bash
BEFORE=$1
AFTER=$1
FILE=/tmp/.cattmp
PATTERN="$2"
cat > $FILE
for i in $(grep -n "$PATTERN" $FILE | sed -e 's/\:.*//')
  do head -n $(($AFTER+$i)) $FILE | tail -n $(($AFTER+$BEFORE+1))
done
rm $FILE

Сохраните этот файл как grep-context.shи замените grep -C1на ./grep-context.sh 1в моей команде выше.

Другой способ, который, как мне кажется, поможет раз и навсегда, — это скомпилировать GNU grep на AIX. (также скомпилируйте GNU sed на всякий случай)

решение3

Вы можете использовать этот скрипт:

#!/bin/sh
read START
read END
read MATCH

REND=$(grep -n "$END" lines | tail -1 | cut -d":" -f 1)
RSTART=$(grep -n "$START" lines | head -1 | cut -d":" -f 1)

sed $RSTART,$REND!d lines | grep "$MATCH"

Поместите его в файл и добавьте разрешение на выполнение с помощью этой команды

chmod +x script.sh

Переменная START:Ваш стартовый номер (например, 0010)

КОНЕЦ переменной:Ваша конечная переменная (например, 0070)

Переменная СОВПАДЕНИЯ:Слово/символ/число, которое вы ищете в строке (например, 0012)

Переменная RSTART:Номер начальной строки в текстовом файле (например, 1)

Переменная REND:Номер начальной строки в текстовом файле (например, 32)


РЕДАКТИРОВАТЬ:

Вы также можете увидеть, сколько раз повторяется строка, изменив последнюю строку следующим образом:

sed $RSTART,$REND!d lines | grep "$MATCH" | sort | uniq -c

Связанный контент