Come abbinare la stringa esatta usando `sed`? Ma non la parte di esso.


8

Ho un file di input FILE1.TXT come di seguito.


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

Voglio cercare tutti i campi che appartengono a un particolare ID e ottenere il valore per NAME

Sono riuscito a scorrere ogni ID e ho formato il comando seguente per ciascun ID come richiesto.

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

Il problema qui è che ottengo l'output NAME1 , inoltre ottengo anche NAMEXYZ .

Cosa dovrebbe essere modificato in modo da ottenere solo NAME1 ma non NAMEXYZ ?

Come soluzione alternativa, i comandi seguenti funzionano.

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

C'è qualche "interruttore" o mi manca qualcosa?

Risposte:


3

Se conosci i numeri di riga che vuoi cercare (come suggerisce la tua Q), stringi la regex in modo da non corrispondere alle linee indesiderate.

Ad esempio, modifica:

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

per

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

Il ^corrisponderà l'inizio della linea e uno spazio dopo le garanzie numero che il numero di riga specifico sarà abbinato, e non sarà elaborare blocchi indesiderati.


Questo sarebbe d'aiuto. Ma come posso abbinare ^(random no of spaces)11?
Vinay,

1
@VinayChalluru usesed -n '/^\s*11 /,/^\s*14 /p'
casey

1
può essere di breve durata usando sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' hai provato questo?
Rahul Patil,

@RahulPatil Sì, funziona.
Vinay

6

Usa i confini delle parole:

grep '\bNAME1\b'

corrisponderebbe NAME1e no NAME1XYZo XYZNAME1.

Allo stesso modo,

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

non corrisponderebbe alle righe contenenti 111e 142.


EDIT: sembra che i numeri nel file di input siano in realtà numeri di riga. In tal caso, potresti semplicemente dire:

sed '11,14!d'

per ottenere le linee desiderate.


C'è solo uno NAMEtra le linee 11 e 14. Quindi, perché sta sedguardando 111e 114? Come farlo non guardare tra 111e 114?
Vinay

@VinayChalluru Vedi la risposta sopra per come è possibile modificare l' sedespressione.
Devnull

Questo risponde alla mia domanda, immagino. Fammi provare e farti sapere.
Vinay,

per confini di parole, grepcon -wbandiera? non è vero?
Rahul Patil

1
@RahulPatil Yup, per l'esempio sopra -wsarebbe equivalente. Per l' sedesempio, -wè leggermente diverso.
Devnull

4

Puoi usare AWK

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

Questo apparirà tra 13 e 17, quindi cerca il nome e, se corrisponde, stampa l'ultima parola da Name = LastWord


Quando provo a fare questo, ricevo un errore che dice che il numero della riga di input deve essere inferiore a 199.
Vinay

@VinayChalluru puoi mostrarmi l'output con il comando, utilizzare paste.ubuntu.com
Rahul Patil

Scuse. Ho aggiunto un $prima NRe quello ha causato l'errore.
Vinay,

@VinayChalluru Va bene. va bene hai provato / testato ogni anno e imparato qualcosa di nuovo ..: D
Rahul Patil

Esattamente. C'è molto di più avanti. :-)
Vinay

4

Non hai bisogno di altri strumenti per questo, sedlo gestirai facilmente intero.

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

Ciò dovrebbe fornire solo la prima sequenza di caratteri non bianchi dopo la frase "NAME =" per ogni riga su cui viene trovata la frase tra le righe 11 e 14 di qualsiasi file di input sed.


3

sed non è lo strumento giusto per questo lavoro. Usa awk dove puoi specificare l'id che stai cercando e stampare il prossimo NAME che appare.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename

Potresti spiegare la riga due e tre del tuo comando awk?
erik,

0

versione generica non basata sul numero di riga ma sul riferimento ID

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. carica l'intero file
  2. sezione pulita che non fa parte del gruppo ID (ricorsivo)
  3. prendi semplicemente il valore del contenuto NAME nel gruppo
  4. stampa il risultato

0

puoi stampare quelle linee che contengono un motivo corrispondente usando sed come segue:

sed -n '/pattern/p'  Filename
  • -n- queste opzioni disabilitano questa stampa automatica e sed produce output solo quando esplicitamente richiesto tramite il pcomando.

  • p - Stampa

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.