Как разделить строку, но также и сохранить разделители?

Это ваш код:

<?php

    define("DB_HOST", "localhost");
    define("DB_USER", "root");
    define("DB_PASSWORD", "");
    define("DB_DATABASE", "databasename");

    $db = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_DATABASE);

?>

Единственной ошибкой, которая вызывает это сообщение, является то, что:

  1. вы определяете DB_USER, но вы вызов [as] как DB_USERNAME.

Пожалуйста, будьте внимательнее в следующий раз.

Лучше для программиста начального уровня, который хочет начать кодирование в PHP не использовать то, что он или она не знает очень хорошо.

ТОЛЬКО в качестве совета попробуйте использовать (в первый раз) код более повсеместно.

ex: не используйте инструкцию define(), попробуйте использовать объявление переменных как $db_user = 'root';

Имейте приятный опыт:)

222
задан Daniel Rikowski 5 February 2010 в 10:00
поделиться

13 ответов

Вы можете использовать Lookahead и Lookbehind. Например, так:

System.out.println(Arrays.toString("a;b;c;d".split("(?<=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("(?=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("((?<=;)|(?=;))")));

И вы получите:

[a;, b;, c;, d]
[a, ;b, ;c, ;d]
[a, ;, b, ;, c, ;, d]

Последнее - то, что вам нужно.

((?<=;)|(?=;)) равносильно тому, чтобы выбрать пустой символ до ; или после ;.

Надеюсь, это поможет.

EDIT Замечания Фабиана Стига по поводу читабельности справедливы. Читабельность всегда является проблемой для RegEx. Чтобы облегчить эту проблему, я создаю переменную, имя которой представляет то, что делает регекс, и использую формат Java String, чтобы помочь в этом. Например, так:

static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))";
...
public void someMethod() {
...
final String[] aEach = "a;b;c;d".split(String.format(WITH_DELIMITER, ";"));
...
}
...

Это немного помогает. :-D

337
ответ дан 23 November 2019 в 03:59
поделиться

Быстрый ответ: используйте не физические границы как \b для разделения. Я попытаюсь экспериментировать, чтобы видеть, работает ли это (использовал это в PHP и JS).

Это возможно, и вид работы, но могло бы разделить слишком много. На самом деле это зависит от строки, которую Вы хотите разделить и результат, в котором Вы нуждаетесь. Предоставьте больше подробную информацию, мы поможем Вам лучше.

Иначе должен сделать Ваше собственное разделение, получив разделитель (предположение, что это является переменным), и добавление его позже к результату.

Мой быстрый тест:

String str = "'ab','cd','eg'";
String[] stra = str.split("\\b");
for (String s : stra) System.out.print(s + "|");
System.out.println();

Результат:

'|ab|','|cd|','|eg|'|

Немного слишком много...:-)

0
ответ дан PhiLho 23 November 2019 в 03:59
поделиться

Я не знаю о существующей функции в API Java, который делает это (который не должен говорить, что не существует), но вот моя собственная реализация (один или несколько разделителей будут возвращены как единственный маркер; если Вы захотите, чтобы каждый разделитель был возвращен как отдельный маркер, будет требоваться немного адаптации):

static String[] splitWithDelimiters(String s) {
    if (s == null || s.length() == 0) {
        return new String[0];
    }
    LinkedList<String> result = new LinkedList<String>();
    StringBuilder sb = null;
    boolean wasLetterOrDigit = !Character.isLetterOrDigit(s.charAt(0));
    for (char c : s.toCharArray()) {
        if (Character.isLetterOrDigit(c) ^ wasLetterOrDigit) {
            if (sb != null) {
                result.add(sb.toString());
            }
            sb = new StringBuilder();
            wasLetterOrDigit = !wasLetterOrDigit;
        }
        sb.append(c);
    }
    result.add(sb.toString());
    return result.toArray(new String[0]);
}
1
ответ дан bdumitriu 23 November 2019 в 03:59
поделиться

Мне нравится идея StringTokenizer, потому что это является Счетным.
, Но это является также устаревшим, и замена String.split, которые возвращают скучную Строку [] (и не делает включает разделители).

, Таким образом, я реализовал StringTokenizerEx, который является Повторяемым, и который берет истинный regexp для разделения строки.

А истинный regexp означает, что это не 'Последовательность символов', повторенная для формирования разделителя:
'o' будет только соответствовать 'o' и разделять 'ooo' на три разделителя с двумя пустыми строками внутри:

[o], '', [o], '', [o]

, Но regexp o + возвратит ожидаемый результат при разделении "aooob"

[], 'a', [ooo], 'b', []

Для использования этого StringTokenizerEx:

final StringTokenizerEx aStringTokenizerEx = new StringTokenizerEx("boo:and:foo", "o+");
final String firstDelimiter = aStringTokenizerEx.getDelimiter();
for(String aString: aStringTokenizerEx )
{
    // uses the split String detected and memorized in 'aString'
    final nextDelimiter = aStringTokenizerEx.getDelimiter();
}

код этого класса доступен по телефону Отрывки DZone .

, Как обычно, для проблема кода ответ (один автономный класс с включенными тестовыми сценариями), вставка копии это (в 'src/test' каталоге) и выполняет его . Его основное () метод иллюстрирует различные использования.

<час>

Примечание: (в конце редактирования 2009 года)

Последние мысли статьи : Трудный вопрос Java: Крохоборствование делает хорошую работу, объясняя причудливое поведение в String.split().
Josh Bloch даже прокомментировал в ответ на ту статью:

Да, это - боль. FWIW, это было сделано на очень серьезном основании: совместимость с Perl.
парнем, который сделал это, является Mike "madbot" McCloskey, который теперь работает с нами в Google. Mike удостоверился, что регулярные выражения Java прошли фактически каждые из 30K тестов регулярного выражения Perl (и работал быстрее).

общая библиотека Google Гуава содержит также Разделитель, который является:

  • более простой использовать
  • сохраняемый Google (а не Вами)

, Таким образом, это может стоящий проверения. От их первоначальная грубая документация (PDF) :

JDK имеет это:

String[] pieces = "foo.bar".split("\\.");

хорошо использовать это, если Вы хотите точно, что это делает: - регулярное выражение - заканчиваются как массив - его способ обработать пустые части

Мини-трудный вопрос: ", a, b", .split ("") возвраты...

(a) "", "a", "", "b", ""
(b) null, "a", null, "b", null
(c) "a", null, "b"
(d) "a", "b"
(e) None of the above

Ответ: (e) Ни одно из вышеупомянутого.

",a,,b,".split(",")
returns
"", "a", "", "b"

Только запаздывающая порожняя тара пропускается! (Кто знает, что обходное решение предотвращает пропуск? Это - забавное...)

В любом случае, наш Разделитель просто более гибок: поведение по умолчанию упрощенно:

Splitter.on(',').split(" foo, ,bar, quux,")
--> [" foo", " ", "bar", " quux", ""]

, Если Вы хотите дополнительные функции, попросите их!

Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split(" foo, ,bar, quux,")
--> ["foo", "bar", "quux"]

Порядок методов конфигурации не имеет значения - во время разделения, обрезка происходит прежде, чем проверить на порожнюю тару.

7
ответ дан Community 23 November 2019 в 03:59
поделиться

Я взглянул на вышеупомянутые ответы, и честно ни один из них я нахожу удовлетворительными. То, что Вы хотите сделать, по существу подражать функциональности разделения Perl. Почему Java не позволяет это и имеет соединение (), метод где-нибудь вне меня, но я отступаю. Вам даже не нужен класс для этого действительно. Его просто функция. Запустите эту программу программы:

Некоторые более ранние ответы имеют чрезмерную проверку пустого указателя, которую я недавно записал ответу на вопрос здесь:

https://stackoverflow.com/users/18393/cletus

Так или иначе, код:

public class Split {
    public static List<String> split(String s, String pattern) {
        assert s != null;
        assert pattern != null;
        return split(s, Pattern.compile(pattern));
    }

    public static List<String> split(String s, Pattern pattern) {
        assert s != null;
        assert pattern != null;
        Matcher m = pattern.matcher(s);
        List<String> ret = new ArrayList<String>();
        int start = 0;
        while (m.find()) {
            ret.add(s.substring(start, m.start()));
            ret.add(m.group());
            start = m.end();
        }
        ret.add(start >= s.length() ? "" : s.substring(start));
        return ret;
    }

    private static void testSplit(String s, String pattern) {
        System.out.printf("Splitting '%s' with pattern '%s'%n", s, pattern);
        List<String> tokens = split(s, pattern);
        System.out.printf("Found %d matches%n", tokens.size());
        int i = 0;
        for (String token : tokens) {
            System.out.printf("  %d/%d: '%s'%n", ++i, tokens.size(), token);
        }
        System.out.println();
    }

    public static void main(String args[]) {
        testSplit("abcdefghij", "z"); // "abcdefghij"
        testSplit("abcdefghij", "f"); // "abcde", "f", "ghi"
        testSplit("abcdefghij", "j"); // "abcdefghi", "j", ""
        testSplit("abcdefghij", "a"); // "", "a", "bcdefghij"
        testSplit("abcdefghij", "[bdfh]"); // "a", "b", "c", "d", "e", "f", "g", "h", "ij"
    }
}
9
ответ дан Community 23 November 2019 в 03:59
поделиться

Я стал здесь опаздывающим, но возвращающийся к исходному вопросу, почему не просто используют lookarounds?

Pattern p = Pattern.compile("(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)");
System.out.println(Arrays.toString(p.split("'ab','cd','eg'")));
System.out.println(Arrays.toString(p.split("boo:and:foo")));

вывод:

[', ab, ',', cd, ',', eg, ']
[boo, :, and, :, foo]

РЕДАКТИРОВАНИЕ: То, что Вы видите выше, - то, что появляется на командной строке, когда я выполняю тот код, но я теперь вижу, что это немного сбивает с толку. Трудно отслеживать, которых запятые являются частью результата и которые были добавлены Arrays.toString(). Подсветка синтаксиса SO не помогает также. В надежде на то, чтобы заставлять выделение работать с меня вместо против меня, вот то, как те массивы посмотрели бы он, я объявлял их в исходном коде:

{ "'", "ab", "','", "cd", "','", "eg", "'" }
{ "boo", ":", "and", ":", "foo" }

я надеюсь, что это легче считать. Спасибо за предостережение, @finnw.

11
ответ дан Alan Moore 23 November 2019 в 03:59
поделиться
import java.util.regex.*;
import java.util.LinkedList;

public class Splitter {
    private static final Pattern DEFAULT_PATTERN = Pattern.compile("\\s+");

    private Pattern pattern;
    private boolean keep_delimiters;

    public Splitter(Pattern pattern, boolean keep_delimiters) {
        this.pattern = pattern;
        this.keep_delimiters = keep_delimiters;
    }
    public Splitter(String pattern, boolean keep_delimiters) {
        this(Pattern.compile(pattern==null?"":pattern), keep_delimiters);
    }
    public Splitter(Pattern pattern) { this(pattern, true); }
    public Splitter(String pattern) { this(pattern, true); }
    public Splitter(boolean keep_delimiters) { this(DEFAULT_PATTERN, keep_delimiters); }
    public Splitter() { this(DEFAULT_PATTERN); }

    public String[] split(String text) {
        if (text == null) {
            text = "";
        }

        int last_match = 0;
        LinkedList<String> splitted = new LinkedList<String>();

        Matcher m = this.pattern.matcher(text);

        while (m.find()) {

            splitted.add(text.substring(last_match,m.start()));

            if (this.keep_delimiters) {
                splitted.add(m.group());
            }

            last_match = m.end();
        }

        splitted.add(text.substring(last_match));

        return splitted.toArray(new String[splitted.size()]);
    }

    public static void main(String[] argv) {
        if (argv.length != 2) {
            System.err.println("Syntax: java Splitter <pattern> <text>");
            return;
        }

        Pattern pattern = null;
        try {
            pattern = Pattern.compile(argv[0]);
        }
        catch (PatternSyntaxException e) {
            System.err.println(e);
            return;
        }

        Splitter splitter = new Splitter(pattern);

        String text = argv[1];
        int counter = 1;
        for (String part : splitter.split(text)) {
            System.out.printf("Part %d: \"%s\"\n", counter++, part);
        }
    }
}

/*
    Example:
    > java Splitter "\W+" "Hello World!"
    Part 1: "Hello"
    Part 2: " "
    Part 3: "World"
    Part 4: "!"
    Part 5: ""
*/

мне действительно не нравится другой путь, где Вы получаете пустой элемент впереди и назад. Разделитель обычно не вначале или в конце строки, таким образом Вы чаще всего заканчиваете тем, что тратили впустую две хороших ячейки массива.

Редактирование: Фиксированные предельные случаи. Прокомментированный источник с тестовыми сценариями может быть найден здесь: http://snippets.dzone.com/posts/show/6453

22
ответ дан Markus Jarderot 23 November 2019 в 03:59
поделиться

Я не знаю Java слишком хорошо, но если Вы не можете найти метод Разделения, который делает это, я предлагаю, чтобы Вы просто сделали свое собственное.

string[] mySplit(string s,string delimiter)
{
    string[] result = s.Split(delimiter);
    for(int i=0;i<result.Length-1;i++)
    {
        result[i] += delimiter; //this one would add the delimiter to each items end except the last item, 
                    //you can modify it however you want
    }
}
string[] res = mySplit(myString,myDelimiter);

не слишком изящный, но это сделает.

-2
ответ дан Alon L 23 November 2019 в 03:59
поделиться

Очень наивным решением, не использующим регулярное выражение, было бы выполнить замену строки в вашем разделителе по строкам (предполагая запятую в качестве разделителя):

string.replace(FullString, "," , "~,~")

Где вы можете заменить тильду (~) соответствующим уникальным разделителем.

Тогда, если вы сделаете разделение на новом разделителе, я думаю, вы получите желаемый результат.

29
ответ дан 23 November 2019 в 03:59
поделиться

Если требуется округлить , используйте Math.ceil:

Math.max( Math.ceil(number2 * 10) / 10, 2.8 )
-121--2190521-

Можно использовать Lookahead и Lookbehind. Вот так:

System.out.println(Arrays.toString("a;b;c;d".split("(?<=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("(?=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("((?<=;)|(?=;))")));

И вы получите:

[a;, b;, c;, d]
[a, ;b, ;c, ;d]
[a, ;, b, ;, c, ;, d]

Последний - это то, что вы хотите.

((? < =;) | (? =;)) равно выделению пустого символа перед ; или после ; .

Надеюсь, это поможет.

EDIT Fabian Steeg комментирует удобочитаемость. Читаемость всегда является проблемой для RegEx. Первое, что я делаю, чтобы облегчить это, это создать переменную, имя которой представляет то, что делает регекс, и использовать формат Java String, чтобы помочь этому. Например:

static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))";
...
public void someMethod() {
...
final String[] aEach = "a;b;c;d".split(String.format(WITH_DELIMITER, ";"));
...
}
...

Это помогает немного.: -D

-121--602650-

Я предлагаю использовать Pattern и Matcher, которые почти наверняка достигнут желаемого. Регулярное выражение должно быть несколько сложнее, чем в String.split.

1
ответ дан 23 November 2019 в 03:59
поделиться

Я не думаю, что это возможно с String#split, но вы можете использовать StringTokenizer, хотя это не позволит вам определить разделитель как regex, а только как класс однозначных символов:

new StringTokenizer("Hello, world. Hi!", ",.!", true); // true for returnDelims
1
ответ дан 23 November 2019 в 03:59
поделиться

Если вы можете себе позволить, используйте метод Java replace (CharSequence target, CharSequence replace) и заполните другой разделитель для разделения. {{ 1}} Пример: Я хочу разделить строку "boo: and: foo" и оставить ':' в правой строке.

String str = "boo:and:foo";
str = str.replace(":","newdelimiter:");
String[] tokens = str.split("newdelimiter");

Важное примечание: это работает только в том случае, если в вашей строке больше нет «newdelimiter»! Таким образом, это не общее решение. Но если вы знаете CharSequence, вы можете быть уверены, что он никогда не появится в String, это очень простое решение.

1
ответ дан 23 November 2019 в 03:59
поделиться

Вы хотите использовать поисковые обходы и разбивать на совпадения нулевой ширины. Вот несколько примеров:

public class SplitNDump {
    static void dump(String[] arr) {
        for (String s : arr) {
            System.out.format("[%s]", s);
        }
        System.out.println();
    }
    public static void main(String[] args) {
        dump("1,234,567,890".split(","));
        // "[1][234][567][890]"
        dump("1,234,567,890".split("(?=,)"));   
        // "[1][,234][,567][,890]"
        dump("1,234,567,890".split("(?<=,)"));  
        // "[1,][234,][567,][890]"
        dump("1,234,567,890".split("(?<=,)|(?=,)"));
        // "[1][,][234][,][567][,][890]"

        dump(":a:bb::c:".split("(?=:)|(?<=:)"));
        // "[][:][a][:][bb][:][:][c][:]"
        dump(":a:bb::c:".split("(?=(?!^):)|(?<=:)"));
        // "[:][a][:][bb][:][:][c][:]"
        dump(":::a::::b  b::c:".split("(?=(?!^):)(?<!:)|(?!:)(?<=:)"));
        // "[:::][a][::::][b  b][::][c][:]"
        dump("a,bb:::c  d..e".split("(?!^)\\b"));
        // "[a][,][bb][:::][c][  ][d][..][e]"

        dump("ArrayIndexOutOfBoundsException".split("(?<=[a-z])(?=[A-Z])"));
        // "[Array][Index][Out][Of][Bounds][Exception]"
        dump("1234567890".split("(?<=\\G.{4})"));   
        // "[1234][5678][90]"

        // Split at the end of each run of letter
        dump("Boooyaaaah! Yippieeee!!".split("(?<=(?=(.)\\1(?!\\1))..)"));
        // "[Booo][yaaaa][h! Yipp][ieeee][!!]"
    }
}

И да, в последнем шаблоне это утверждение с тройной вложенностью.

Связанные вопросы

См. Также

75
ответ дан 23 November 2019 в 03:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: