Controleer of het bestand een string bevat

Dus ik vond deze vraag hier, maar ik heb een probleem met de uitvoer en hoe om te gaan met een if-statement. Dit is wat ik heb, maar het zegt altijd dat het waar is, zelfs als het woord monitor niet bestaat in het bestand

if File.readlines("testfile.txt").grep(/monitor/)
  do something
end

Moet het zoiets als == "nul" zijn? Ik ben redelijk nieuw voor robijn en niet zeker van wat de resultaten zouden zijn.

32
Opmerking: het gebruik van readlines kan echt problemen veroorzaken als het bestand groter is dan het beschikbare geheugen. Zie " Waarom slurpt een bestand slecht? " voor meer informatie.
toegevoegd de auteur the Tin Man, de bron

4 antwoord

Ik zou gebruiken:

if File.readlines("testfile.txt").grep(/monitor/).any?

of

if File.readlines("testfile.txt").any?{ |l| l['monitor'] }

Het gebruik van readlines heeft echter schaalbaarheidsproblemen omdat het het volledige bestand in een array leest. In plaats daarvan zal het gebruik van foreach hetzelfde bereiken zonder het probleem van de schaalbaarheid:

if File.foreach("testfile.txt").grep(/monitor/).any?

of

if File.foreach("testfile.txt").any?{ |l| l['monitor'] }

See "Why is "slurping" a file not a good practice?" fofmore information about the scalability issues.

53
toegevoegd
+1 voor any? , omdat dit eindigt zodra het de eerste match vindt in plaats van elke regel te verwerken, alleen om te zien of er een match is.
toegevoegd de auteur Phrogz, de bron
Houd in gedachten dat dit niet idempotent is. Als u het twee keer achter elkaar uitvoert, wordt tijdens de eerste keer true geretourneerd en false op de tweede. U moet het bestand terugspoelen voordat u het opnieuw uitvoert.
toegevoegd de auteur David Tuite, de bron
Het is niet nodig om rewind in te voeren. leesregels opent en sluit het bestand automatisch, zodat het altijd begint bij het begin en tot het einde leest.
toegevoegd de auteur the Tin Man, de bron

Enumerable#grep does not return a boolean; it returns an array (how would you have access to the matches without passing a block otherwise?).

Als er geen overeenkomsten worden gevonden, wordt een lege array geretourneerd en wordt [] geëvalueerd naar true . U moet de grootte van de array controleren in de instructie if , d.w.z.

if File.readlines("testfile.txt").grep(/monitor/).size > 0
  # do something
end

De documentatie moet uw eerste hulpmiddel zijn voor vragen als deze.

27
toegevoegd
Bedankt voor dit bericht. je hebt me daar veel mee geholpen. maar ik vroeg me af of ik een pad moest zoeken?
toegevoegd de auteur MZaragoza, de bron
Ik ben op zoek naar een string in een bestand dat eruit ziet als "/www/assests/2015/09/18/someimage.png" het probleem is dat er andere afbeeldingennamen 'someimage.png' zijn in andere mappen
toegevoegd de auteur MZaragoza, de bron
@MZaragoza: hangt af van wat voor soort pad. Ik weet zeker dat als je naar reguliere expressies zoekt om een ​​pad te matchen, je een flink aantal voorbeelden zult vinden.
toegevoegd de auteur Ed S., de bron
Voor paden wilt u misschien een reguliere expressie in grep gebruiken. Voor bijvoorbeeld; File.readlines ( "/ home/# {os_user}/bash_profile.") Grep (% r {JAV & zwnj; A_HOME = \/opt \/Oracle & zwnj; \/jdk}). Leeg.?
toegevoegd de auteur Abhishek Prusty, de bron

Grep geeft je een reeks van alle gevonden 'monitors'. Maar u wilt geen array, u wilt een boolean: staat er een 'monitor' string in dit bestand? Deze leest zo weinig van het bestand als nodig:

if File.open('test.txt').lines.any?{|line| line.include?('monitor')}
  p 'do something'
end

readlines reads the whole file, lines returns an enumerator which does it line by line.

6
toegevoegd

als iemand op zoek is naar een oplossing om de laatste regel van een bestand weer te geven waar die reeks voorkomt, doe het dan gewoon

File.readlines('dir/testfile.txt').select{|l| l.match /monitor/}.last 

bijvoorbeeld

het dossier:

monitor 1
monitor 2
something else

je zult krijgen

monitor 2
0
toegevoegd