Home > front end >  Write a procedure loadDocument(String name) which will load and analyze lines after lines searching
Write a procedure loadDocument(String name) which will load and analyze lines after lines searching

Time:03-10

Write a procedure loadDocument(String name) which will load and analyze lines after lines searching for link in every line. The link format is as follows: 5 characters link= (it can be mixed capital and small letters) after which there is a correct identifier. The correct identifier starts from letter (small or capital) follows by zero or more occurrences of letters or digits or underline _. The procedure has to print subsequent identifiers, each one in a separated line. Before printing, the identifiers have to be changed to small letters. The document ends with line with the text eod, which means end of document.

My code:

public static void loadDocument(String name, Scanner scan) {
    while(scan.hasNext()) {
        String line = scan.nextLine();
        if(line.equals("eod")) {
            return;
        }
        else if(line.matches("link=" name) && correctLink(name)) {
            String identifier = name.toLowerCase();
            System.out.println(identifier);
        }
        else
            continue;
    }            
}

// accepted only small letters, capital letter, digits and '_' (but not on the begin)
public static boolean correctLink(String link) {
    if(link.matches("^[a-zA-Z] [0] ||[0-9] ||_"))
        return true;
    else
        return false;
}

How to write if line equal to link=, return whatever's after link=? My problem is in this code:

else if(line.matches("link=" name) && correctLink(name)) {
    String identifier = name.toLowerCase();
    System.out.println(identifier);
}

For example, if the input is link=abc, I want it to print abc.

CodePudding user response:

First I would suggest that you get used to compare to literal strings "the other way round" - this will save you from a lot NullPointerExceptions (but this is just a side comment):

if ("eod".equals(line))

You can use @Ofer s example (it is generated from https://regex101.com, a nice page to play around with regular expressions and get them explained btw.) but you should use a different regex:

final String regex = "link=([a-z][a-z0-9_]*)";

and a different option for the pattern:

final Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

I used the CASE_INSENSITIVE option to make the "link" also trigger for mixed case writings (like "Link", "liNk" and so on). Therefore I also could skip the uppercase letters from the actual regex, as [a-z] will also match uppercase letters with that option, and that's what was requested.

The "magic" here is that you put the expression that you later want to "read" from the pattern matcher into parenthesis "()" - this marks a "group". Group 0 always gives back the full match (including the "link=" here).

You can play around with that expression at https://regex101.com/r/id2CP2/1

Please don't forget to convert the identifiers (you get them from matcher.group(i)) to lowercase before you output them.

CodePudding user response:

here is an example that explains it all:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Example {
    public static void main(String[] args) {
        final String regex = "link=(.*)";
        final String string = "link=sdfgubvcyx";
        
        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);
        
        while (matcher.find()) {
            System.out.println("Full match: "   matcher.group(0));
            
            for (int i = 1; i <= matcher.groupCount(); i  ) {
                System.out.println("Group "   i   ": "   matcher.group(i));
            }
        }
    }
}

regex - the text link= followed by a group that is made up of any combination of characters (any character even whitespaces etc).
string - just my test string.
pattern - the compiled regex.
matcher - the matcher in the compiled regex for my test string.
matcher.group(0) - the full match.
matcher.group(1) - the match for first group (this is what you are looking for).
you can do it in 2 lines, but I think this makes it clearer :)

  • Related