Como combinar a string exata usando o `sed`? Mas não é a parte disso.

8

Eu tenho um arquivo de entrada FILE1.TXT como abaixo.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

Quero pesquisar todos os campos que pertencem a um ID específico e obter o valor para NAME

Consegui fazer um loop através de cada ID e formei o comando abaixo para cada ID, conforme necessário.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

O problema aqui é que eu recebo a saída NAME1 , além disso, também recebo NAMEXYZ .

O que deve ser alterado para que eu receba apenas NAME1, mas não NAMEXYZ ?

Como solução alternativa, os comandos abaixo funcionam.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

Existe alguma opção ou estou faltando alguma coisa?

Vinay
fonte

Respostas:

3

Se você souber os números de linha que deseja pesquisar (como sugere seu Q), aperte a regex para não corresponder às linhas indesejadas.

Por exemplo, altere:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

para

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

O valor ^corresponderá ao início da linha e um espaço após o número garante que o número da linha específico seja correspondido e você não processará blocos indesejados.

Casey
fonte
Isso ajudaria. Mas como posso combinar ^(random no of spaces)11?
Vinay
1
@VinayChalluru usesed -n '/^\s*11 /,/^\s*14 /p'
casey
1
pode ser mão curta usando sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' você já tentou isso?
Rahul Patil 03/03
@RahulPatil Sim, funciona.
Vinay
6

Use limites de palavras:

grep '\bNAME1\b'

corresponderia NAME1e não NAME1XYZou XYZNAME1.

Similarmente,

sed -n '/11\b/,/14\b/p'

não corresponderia a linhas contendo 111e 142.


EDIT: Parece que os números no arquivo de entrada são realmente números de linha. Se for esse o caso, você poderia simplesmente dizer:

sed '11,14!d'

para obter as linhas desejadas.

devnull
fonte
Existe apenas uma NAMEentre as linhas 11 e 14. Então, por que está sedolhando 111e 114? Como fazê-lo não parecer entre 111e 114?
Vinay
@VinayChalluru Veja a resposta acima para saber como você pode modificar a sedexpressão.
devnull 03/03
Isso responde a minha pergunta, eu acho. Deixe-me tentar e informá-lo.
Vinay
para limites de palavras, grepcom -wbandeira? não é?
Rahul Patil 03/03
1
@RahulPatil Sim, para o exemplo acima -wseria equivalente. Por sedexemplo, -wé um pouco diferente.
devnull 03/03
4

Você pode usar o AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

Aparecerá linhas entre 13 e 17, em seguida, procure por Nome e, se corresponder, imprimirá a última palavra de Name = LastWord

Rahul Patil
fonte
Quando tento fazer isso, recebo um erro dizendo que o número da linha de entrada deve ser menor que 199. #
Vinay
@VinayChalluru você pode me mostrar a saída com o comando, use paste.ubuntu.com
Rahul Patil
Desculpas. Eu adicionei um $antes NRe isso causou o erro.
Vinay
@VinayChalluru It's OK. que é bom que você tentou / testado cada ans e aprender algo novo ..: D
Rahul Patil
Exatamente. Há muito mais pela frente. :-)
Vinay
4

Você não precisa de nenhuma outra ferramenta para isso, sedlidará facilmente com ela inteira.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

Isso deve fornecer apenas a primeira sequência de caracteres que não sejam espaços em branco após a frase "NAME =" para cada linha na qual essa frase é encontrada entre as linhas 11 e 14 de qualquer arquivo de entrada sedé alimentada.

mikeserv
fonte
3

O sed não é a ferramenta certa para este trabalho. Use awk onde você pode especificar o ID que está procurando e imprimir o próximo NAME que aparece.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename
Glenn Jackman
fonte
Você poderia explicar as linhas dois e três do seu comando awk?
Erik
0

versão genérica não baseada no número da linha, mas na referência de identificação

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. carregar o arquivo inteiro
  2. seção limpa que não faz parte do grupo de IDs (recursiva)
  3. basta pegar o valor do conteúdo NAME no grupo
  4. imprima o resultado
NeronLeVelu
fonte
0

você pode imprimir as linhas que contêm o padrão correspondente usando sed da seguinte maneira:

sed -n '/pattern/p'  Filename
  • -n- essas opções desativam essa impressão automática e o sed somente produz saída quando explicitamente solicitado através do pcomando.

  • p - impressão

user182845
fonte