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

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

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

Abaixo estão os dados de amostra. Preciso usar o grep para o número de telefone que está presente no campo 0012 e os registros completos do cliente 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 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.

Responder1

Então você quer o registro completo de 0010 a 0070, se o número PH corresponder $PH_NO"? Então este sedoneliner funcionará:

sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
  • /^0010/,/^0070/Hpara anexar um registro de 0010 a 0070 ao espaço de espera
  • /^0010/ho 0010 não deve ser anexado, mas iniciar um novo registro, então copie-o para o espaço de espera
  • /^0070/! dnenhum processamento ou saída adicional, a menos que seja o item 0070
  • x;/|$PH_NO| PH Number/! d"troque os espaços, para que todo o registro fique no espaço padrão agora e exclua-o se não contiver o referido número.

Responder2

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 222no comando acima está o número de telefone do cliente. Mude para o número de telefone que você deseja descobrir.

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

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

./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 0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file>


ATUALIZAR

Esta é uma versão de alto desempenho. (Pelo menos maior que o original acima. Nenhum loop for envolvido.)

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


ATUALIZAÇÃO para AIX

Já que o solicitante 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 GNU grep). Mas a maioria deles não pode fornecer a mesma saída que o GNU grep. Apenas um que encontrei é o mais próximo da opção de contexto GNU grep. A ligação éhttps://stackoverflow.com/questions/1685678/advanced-grep-unix/1685782#1685782

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 grep-context.she substitua -o grep -C1no ./grep-context.sh 1meu comando acima.

Outra maneira que penso ser de uma vez por todas é compilar o GNU grep no AIX. (também compile GNU sed apenas por precaução)

Responder3

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-o em um arquivo e adicione a permissão de execução com este comando

chmod +x script.sh

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

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

Variável CORRESPONDÊNCIA: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 arquivo 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 se repetiu, alterando a última linha para isto:

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

informação relacionada