0

i want get text from a file by using regEx and want save the file with a new name (using the results of the regEx-Find).

My Problem is that i cant get/return the correct genearated (in this example xyz maur) out of the function readFileLineByLineUsingForEachLine(fileName: String) the new newFileName which was generated (sucessfully as expected) in the function.

Line 1 of Source:

start {"Name":"xyz","Civ":"maur","Team":0}

My Prototype:

fun main() {
    val f = "./commands.txt";
    var newFileName = readFileLineByLineUsingForEachLine(f)
    print(newFileName.)
    val source = Paths.get(f)
    val target = Paths.get("/home/x/snap/0ad/199/.local/share/0ad/replays/0.0.24/2021-03-14_0016/" + newFileName)
//    try {
//        val move = Files.move(
//            source,
//            target
//        )
//    } catch (e: IOException) {
//        e.printStackTrace()
//    }
};

fun readFileLineByLineUsingForEachLine(fileName: String) // https://www.baeldung.com/kotlin/read-file
        = File(fileName).forEachLine lit@{
    // "Name":"Cleisthenes"
    val regexString = """
    "Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0
            """.trim()
    var regex = Regex(regexString)
    var matched = regex.find(it)?.groupValues
    val Name = matched?.get(1)
    val Civ = matched?.get(2)
    if (Name != null)
        println(Name)
    if (Civ != null)
        println(Civ)
    val newFileName = "$Name $Civ"
    return@lit
}
Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
SL5net
  • 2,282
  • 4
  • 28
  • 44
  • Could you include your source file and desired output? Also, if the file is XML, then using an XML parser would be a better idea than trying to use regular expressions. See also https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – Adam Millerchip Mar 16 '21 at 03:37
  • @AdamMillerchip Line 1 of Source: `start {"Name":"xyz","Civ":"maur","Team":0}` as i said. parsing the source is not my problem – SL5net Mar 16 '21 at 10:45
  • 1
    What's with the attitude problem? "as I said" - you didn't say that, you edited it in two minutes before your comment. The sample input will make it easier for people to understand what you are trying to do, so I think it was worth adding. – Adam Millerchip Mar 16 '21 at 11:03
  • 1
    Do you want `readFileLineByLineUsingForEachLine` to return the file name `xyz maur`? – Adam Millerchip Mar 16 '21 at 11:09
  • 'i cant get out of the function'. I am a native German speaker. I try my best to speak in english. do I have to explain something else? I will need the result later for a new file name. – SL5net Mar 16 '21 at 11:10

2 Answers2

1

Because you want to stop processing as soon as you find a match, I don't think forEachLine is the best choice. Instead you can use useLines, and combine it with first to stop processing once you get a match:

val regex = Regex(""""Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0""")

fun readFileLineByLineUsingForEachLine(fileName: String) =
    File(fileName).useLines { lines ->
        val (name, civ) = lines
            .map { regex.find(it) }
            .filterNotNull()
            .first()
            .destructured

        "$name $civ"
    }

For the example you provided, this returns the string "xyz" "maur".

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
  • difficult to reuse your example. i got the error `Unresolved reference: regex`. I will find a solution with it. Thank you – SL5net Mar 16 '21 at 11:58
  • 1
    Ah, sorry I forgot to include the regex definition . Fixed now. I defined it outside the function to avoid re-creating it for every line of the file. – Adam Millerchip Mar 16 '21 at 12:30
  • yours looks a bit more pretty i think. did you tested it? – SL5net Mar 16 '21 at 12:32
  • Yes I tested it. I still think you should consider using a JSON parsing library if this is something you are going to be maintaining for longer that 5 minutes. – Adam Millerchip Mar 16 '21 at 12:34
  • the complete File looks like correct JSON for me: https://i.imgur.com/aC3NMH2.png , https://wildfiregames.com/forum/topic/35314-ratings-disputes-and-offence-reporting/?do=findComment&comment=343612 – SL5net Mar 16 '21 at 12:42
  • 1
    In that file, the input you're looking for is on the first line. So it seems like looping through all the lines is not needed - but it was impossible to tell that from your code sample. This is why providing the input when you ask the question is important. – Adam Millerchip Mar 16 '21 at 14:38
0

that's just a very little modification of the correct, helpful answer from Adam here https://stackoverflow.com/a/66654710/2891692

fun readFileLineByLineUsingForEachLine2(fileName: String) =
    File(fileName).useLines { lines ->
        val (name, civ) = lines
            .map {
                val regexString = """
"Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0
            """.trim()
                var regex = Regex(regexString)
                regex.find(it)
            }
            .filterNotNull()
            .first()
            .destructured
        "$name $civ"
    }
SL5net
  • 2,282
  • 4
  • 28
  • 44