Grep para um conjunto de linhas de $ START a $ END AND que contém uma correspondência no $ MIDDLE

1

Grep / Awk / Sed para um conjunto de linhas de "0010 |" para "0070 |" AND que contém uma correspondência no $ PH_NO

Abaixo estão os dados da amostra. Eu preciso grep para o número de telefone que apresentam no campo 0012 e os registros de clientes completos correspondentes, linhas de 0010 a 0070. Um arquivo de dados pode conter dois ou três registros de clientes com o mesmo número de telefone e eu preciso obter todos eles.

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|

Nota: Estou em um servidor AIX com ksh.

    
por Santhosh Ram 24.11.2017 / 08:50

3 respostas

3

Então você quer o registro inteiro de 0010 a 0070, se o número PH corresponder a $PH_NO" ? Então, esse sed oneliner funcionará:

sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
  • /^0010/,/^0070/H para anexar um registro de 0010 a 0070 ao espaço de espera
  • /^0010/h o 0010 não deve ser acrescentado, mas inicie um novo registro, então copie-o para o espaço de espera
  • /^0070/! d nenhum processamento ou saída adicional, a menos que seja o item 0070
  • x;/|$PH_NO| PH Number/! d" troca os espaços, então o registro inteiro está no espaço padrão agora e exclua se não contiver o número mencionado.
por 24.11.2017 / 12:16
0
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 no comando acima é o número de telefone do cliente. Altere-o para o número de telefone que você deseja descobrir.

CUSTOMER_FILE é o arquivo que você deseja pesquisar. Mude para o seu nome de arquivo.

Você também pode colocar o código em um script básico e substituir 149 196 222 por $1 e substituir CUSTOMER_FILE por $2 . Diga find-customer.sh, então você pode executar o script como este

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

Pré-requisito deste trecho de código:

  1. Bash, ambiente GNU (GNU grep, GNU sed)
  2. Seu arquivo deve seguir o formato abaixo %código%


UPDATE

Esta é uma versão de alto desempenho. (Pelo menos, maior do que o original acima. Não for-loop envolvido em tudo.)

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]+)|,p;a|g' | sed -n -f - CUSTOMER_FILE


UPDATE para AIX

Como o consulente está trabalhando no AIX. O grep no AIX não suporta opções de contexto, -A, -B, -C.

Na Internet, há uma variedade de implementações "cgrep" (context grep) para resolver este problema (para simular a opção de contexto grep do GNU). Mas a maioria deles não pode dar a mesma saída que o GNU grep. Apenas um que eu encontrei é o mais próximo da opção de contexto do GNU grep. O link é link

Eu fiz algumas modificações necessárias para este caso.

#!/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

Salve este arquivo como 0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file> e substitua grep-context.sh por grep -C1 no comando acima.

Outra maneira que eu acho que é de uma vez por todas é compilar o GNU grep no AIX. (também compilar o GNU sed apenas no caso)

    
por 24.11.2017 / 09:56
-1

Você pode usar este script:

#!/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"

Coloque em um arquivo e adicione a permissão de execução com este comando

chmod +x script.sh

Variável START: seu número de linha inicial (por exemplo, 0010)

Variável END: Sua variável final (por exemplo, 0070)

Variável MATCH: A palavra / caractere / número que você está procurando em uma linha (por exemplo, 0012)

Variável RSTART: o número da linha inicial no ficheiro de texto (por exemplo, 1)

variável REND: o número da linha inicial no arquivo de texto (por exemplo, 32)

EDITAR:

Você também pode ver quantas vezes uma linha é repetida, alterando a última linha para esta:

sed $RSTART,$REND!d lines | grep "$MATCH" | sort | uniq -c
    
por 24.11.2017 / 10:35