2015-05-19 12 views
5

Come fare qualcosa di simile a questo codice D e Java in Rust?Come leggere, filtrare e modificare le linee da un file

Java:

import java.nio.file.*; 
import java.io.*; 

public class Main { 
    public static void main(String[] args) throws IOException 
    { 
     Files.lines(Paths.get("/home/kozak/test.txt")) 
      .filter(s -> s.endsWith("/bin/bash")) 
      .map(s -> s.split(":", 2)[0]) 
      .forEach(System.out::println); 
    } 
} 

lingua D:

import std.algorithm; 
import std.stdio; 

void main() { 
    File("/home/kozak/test.txt") 
     .byLine 
     .filter!((s)=>s.endsWith("/bin/bash")) 
     .map!((s)=>s.splitter(":").front) 
     .each!writeln; 
} 

ho provato, ma mi sono perso con tutta questa roba proprietà

il mio codice di ruggine:

use std::io::BufReader; 
use std::fs::File; 
use std::io::BufRead; 
use std::io::Lines; 

fn main() { 
    let file = match File::open("/etc/passwd") { 
     Ok(file) => file, 
     Err(..) => panic!("room"), 
    }; 

    let mut reader = BufReader::new(&file); 
    for line in reader.lines().filter_map(
     |x| if match x { Ok(v) => v.rmatches("/bin/bash").count() > 0, Err(e) => false} 
     { match x { Ok(v2) => Some(v2.split(":").next()), Err(e2) => None }} else 
     { None }) 
    { 
      print!("{}", line.unwrap()); 

    } 
} 
+2

E che cosa hai fatto finora? Dovresti avere abbastanza esperienza per capire che SO non è un sito dove lasci il tuo lavoro "per favore fallo per me" su altre persone. – GhostCat

+0

colpa mia clicco posta troppo presto e non si rendono conto manca la mia prova – Kozzi11

risposta

7

Ecco qui:

use std::fs::File; 
use std::io::{BufRead, BufReader}; 

fn main() { 
    let f = BufReader::new(File::open("/etc/passwd").unwrap()); 
    let it = f.lines() 
     .map(|line| line.unwrap()) 
     .filter(|line| line.ends_with("/bin/bash")) 
     .map(|line| line.split(":").next().unwrap().to_owned()); 
    for p in it { 
     println!("{}", p); 
    } 
} 

Questo codice assegna una stringa separata per ogni prima parte a spacco, però, ma non credo che sia possibile evitarlo, senza lo streaming iteratori. E, naturalmente, la gestione degli errori qui è davvero lassista.

immagino un approccio imperativo sarebbe più idiomatica, soprattutto per quanto riguarda la gestione degli errori:

use std::fs::File; 
use std::io::{BufRead, BufReader}; 

fn main() { 
    let f = BufReader::new(File::open("/etc/passwd").unwrap()); 
    for line in f.lines() { 
     match line { 
      Ok(line) => if line.ends_with("/bin/bash") { 
       if let Some(name) = line.split(":").next() { 
        println!("{}", name); 
       } else { 
        println!("Line does not contain ':'"); 
       } 
      }, 
      Err(e) => panic!("Error reading file: {}", e) 
     } 
    } 
} 
+0

belle grazie mille cosa ne pensate di questa soluzione: http://www.abclinuxu.cz/zpravicky/rust-1.0#58 – Kozzi11

+0

@ Kozzi11 , sembra buono. La formattazione è un po 'off, però, e se insisti a usare gli iteratori è meglio usare alcuni convenienti adattatori iteratori da [itertoos] (https://crates.io/crates/itertools), come 'foreach()', quindi tu non sarà necessario forzare l'iteratore per eseguire con 'last()' o qualcosa del genere. –

+0

@VladimirMatveev La mia formattazione non è ortodossa, sì :) Grazie per aver menzionato itertools, non sapevo che ... – kralyk