在字符串中查找不在双qotes之间的字符

时间:2016-06-03 04:28:24

标签: java string

我想找到(a)特定字符的出现,但要搜索的字符串不能在引号之间:

示例:

"this is \"my\" example string" 

如果你查找char'm',那么它只应该从“example”返回'm'的索引,因为另一个'在双引号之间。

另一个例子:

"th\"i\"s \"is\" \"my\" example string"

我期待的是:

public List<Integer> getOccurrenceStartIndexesThatAreNotBetweenQuotes(String snippet,String stringToFind);

一种“天真”的方式是:

  • 获取snippet

  • 中stringToFind的所有起始索引
  • 获取摘录中所有引号的索引

  • 根据stringToFind的起始索引,因为你有引号的位置,你可以知道你是否在引号之间。

有更好的方法吗?

编辑:

我想要检索什么?匹配的索引。

少数事情:

  • 要搜索的字符串中可以有很多引用的内容:“th \”我的\“是\”\“我的\”示例字符串“

  • 在字符串中:“th”我的\“是\”\“我的\”示例字符串“,”i“,”是“和”我的“在引号之间。

  • 不限于字母和数字,我们可以有'; :()_- = + [] {}等......

3 个答案:

答案 0 :(得分:1)

这是一个解决方案:

<强>算法

  1. 找到所有&#34;死区&#34;字符串中的区域(例如,因为它们在引号内而处于禁区内的区域)
  2. 查找字符串中包含相关搜索字符串的所有区域(代码中为hitZones)。
  3. 仅保留hitZones中未包含在任何deadZones中的区域。我将把这部分留给你:)
  4. import java.util.*;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class FindStrings
    {
        // Just a simple model class for regions
        static class Pair
        {
            int s = 0;
            int e = 0;
    
            public Pair (int s, int e)
            {
                this.s = s;
                this.e = e;
            }
    
            public String toString ()
            {
                return "[" + s + ", " + e + "]";
            }
        }
    
        public static void main(String[] args)
        {
            String search = "other";
    
            String str = "this is \"my\" example other string. And \"my other\" this is my str in no quotes.";
    
            Pattern p = Pattern.compile("\"([^\"]*)\"");
            Matcher m = p.matcher(str);
    
            List<Pair> deadZones = new ArrayList<Pair>();
            while (m.find())
            {
                int s = m.start();
                int e = m.end();
                deadZones.add(new Pair(s, e - 1));
            }
    
            List<Pair> hitZones = new ArrayList<Pair>();
            p = Pattern.compile(search);
            m = p.matcher(str);
            while (m.find())
            {
                int s = m.start();
                int e = m.end();
                hitZones.add(new Pair(s, e - 1));
            }
    
            System.out.println(deadZones);
            System.out.println(hitZones);
        }
    }
    

    注意s中所有Pairs的{​​{1}}组件不在hitZones范围内,最终将成为您想要的

答案 1 :(得分:0)

正如Mamun建议的那样,您可以删除引号之间的所有引号和字符串,然后搜索。以下是一个正则表达式解决方案(虽然我同意Tim的说法,它可能不适用于正则表达式引擎)。

String snippetQuoteRemoved = snippet.replaceAll("(?:\")(\\w+)(?:\")","");
// Now simply search in snippetQuoteRemoved  

注意:这会查找\w+,即([a-zA-Z0-9_])。将其更改为适合您的用例的任何内容。

编辑

我检查了它是否删除了所有内容,但事实并非如此。检查here
此外,对于那些额外的特殊字符,只需将正则表达式更改为(?:")([a-zA-Z0-9_';:()_\-=+\[\]\{\}]+)(?:")

答案 2 :(得分:0)

另一种解决方案:

  • 获取snippet

  • 中stringToFind的所有起始索引
  • 获取摘录中所有引号的索引

  • 根据stringToFind的起始索引,因为你有引号的位置,你可以知道你是否在引号之间。

    public List<Integer> getOccurrenceIndexesNotInQuotes(String snippet,String patternToFind) {
    
        List<Integer> allIndexes = getStartPositions(snippet,patternToFind);
        List<Integer> allQuoteIndexes = getStartPositions(snippet,"\"");
        TreeSet<Integer> allQuoteIndexesTree = new TreeSet<>(allQuoteIndexes);
    
        List<Integer> finalIndexes = new ArrayList<>();
        for (Integer index : allIndexes){
            Integer quoteIndexValue = allQuoteIndexesTree.floor(index);
            int quoteIndex = allQuoteIndexes.indexOf(quoteIndexValue);
            if (quoteIndexValue == null || !isBetweenQuote(quoteIndex)){
                finalIndexes.add(index);
            }
        }
    
        return finalIndexes;
    }
    
    private List<Integer> getStartPositions(String stringToProcess, String regex) {
        List<Integer> out = new ArrayList<>();
    
        Matcher matcher = Pattern.compile(regex).matcher(stringToProcess);
        while(matcher.find()) {
            out.add(matcher.start());
        }
    
        return out;
    }
    
    private boolean isBetweenQuote(Integer indexInQuoteList){
        return indexInQuoteList % 2 != 1;
    }