2010-05-03 7 views

risposta

6

Si può fare con un'espressione regolare. Ecco la stringa che vogliamo per la ricerca:

s = %{The first line 
The second line 
The third line 
The fourth line 
The fifth line 
The sixth line 
The seventh line 
The eight line 
The ninth line 
The tenth line 
} 

EOL è "\ n" per me, ma per voi potrebbe essere "\ r \ n". Io bastone in una costante:

EOL = '\n' 

Per semplificare l'espressione regolare, definiremo il modello per "contesto" solo una volta:

CONTEXT_LINES = 2 
CONTEXT = "((?:.*#{EOL}){#{CONTEXT_LINES}})" 

ed eseguiremo una ricerca per tutte le linee contenente la parola "quinto". Si noti che questa espressione regolare deve afferrare l'intera linea, compresa la linea di fine, per farlo funzionare:

regexp = /.*fifth.*#{EOL}/ 

Infine, fare la ricerca e mostrare i risultati:

s =~ /^#{CONTEXT}(#{regexp})#{CONTEXT}/ 
before, match, after = $1, $2, $3 
p before # => "The third line\nThe fourth line\n" 
p match  # => "The fifth line\n" 
p after  # => "The sixth line\nThe seventh line\n" 
+0

Questo è stato fantastico, grazie! Funziona come un incantesimo - ho dovuto tornare indietro e rileggere che il fine riga deve essere incluso nell'espressione regolare che sto cercando, l'ho perso quando ho inizialmente provato questo. – wonderfulthunk

+0

Questo dovrebbe funzionare: /.*fifth.*[#{EOL}]*/ Vedere http://rubular.com/r/skalXLBXcQ –

0

Non penso che si possa fornire args a grep; basato su api.

È sempre possibile scrivere un metodo. Qualcosa del genere:

def new_grep(enum, pattern, lines) 
values = enum.grep(/pattern/).map do |x| 
    index = enum.index(x) 
    i = (index - lines < 0) ? 0 : index - lines 
    j = (index + lines >= enum.length) ? enum.length-1 : index + lines 
    enum[i..j] 
end 
return values.flatten.uniq 
end 
+0

Questo potrebbe funzionare anche, ma ho trovato la risposta di Wayne per essere più simile a quello che volevo. – wonderfulthunk

2

Grazie per la il grep contestuale. Ho pensato che potrei aggiungere che quando la corrispondenza si avvicina alla parte superiore o inferiore e si desidera che tutte le linee che possano ottenere anche senza tutte le linee CONTEXT_LINES disponibili, è possibile modificare la definizione di CONTEXT come segue:

CONTEXT = "((?:.*#{EOL}){0,#{CONTEXT_LINES}})" 

Per impostazione predefinita, le partite sono avidi, quindi se una parte o la totalità delle linee CONTEXT_LINES disponibili, questo è quello che ti afferra.

Problemi correlati