Строка Java против аргумента командной строки

Почему происходит так, что аргумент командной строки, переданный классу Java, кажется автоматически экранированным, в то время как в экземпляре объекта String экранирующий символ () по-видимому игнорируется.

Например, если начать с такой строки:

SELECT * FROM my_table WHERE my_col like 'ABC_\' ESCAPE '\'

И я пытаюсь запустить его через простой класс, например:

public class EscapeTest {
    public static void main (String[] args) {
        String str = "SELECT * FROM my_table WHERE " 
                     + "my_col like 'ABC_\' ESCAPE '\'";
        System.out.println("ARGS[0]: "+args[0]);
        System.out.println("STR: "+str);
}
}

и я передаю оператор «SELECT» выше в качестве аргумента командной строки, я получаю вывод, который выглядит следующим образом:

ARGS[0]: SELECT * FROM my_table WHERE my_col like 'ABC_\' ESCAPE '\'

STR: SELECT * FROM my_table WHERE my_col like 'ABC_' ESCAPE ''

Если я посмотрю на значение ARGS[0] в отладчике Eclipse, я увижу, что косые черты экранированы. Почему это происходит? По-моему, трудно предсказать.


person Jason Holmberg    schedule 22.07.2011    source источник


Ответы (1)


Содержимое вашей строки str не содержит обратной косой черты. Они обрабатываются компилятором Java, понимающим escape-последовательности строковых литералов Java.

Процессор командной строки, по-видимому, не делает этого — он никаким образом не обрабатывает обратную косую черту, хотя это будет зависеть от вашей оболочки. (В большинстве оболочек Unix обратная косая черта была бы обработана по-разному. Я предполагаю, что вы работаете в Windows.)

Таким образом, ваш аргумент командной строки действительно содержит обратную косую черту. Они не были экранированы исполняемым процессом Java — они просто «там» в строке.

Теперь кажется, что отладчик экранирует строку, когда отображает ее вам, чтобы вы могли видеть такие вещи, как табуляции и новые строки. Важно понимать, что это просто то, как отладчик отображает строку — в самой строке Java нет такого понятия, как «экранирование».

РЕДАКТИРОВАТЬ: Согласно комментарию:

Чтобы выразить эту строку в исходном коде Java, вам нужно экранировать обратную косую черту:

String str = "SELECT * FROM my_table WHERE my_col like 'ABC_\\' ESCAPE '\\'"; 

Обратная косая черта должна быть экранирована, поскольку обратная косая черта является escape-символом в строковых литералах Java.

person Jon Skeet    schedule 22.07.2011
comment
Чтобы, возможно, уточнить ваш правильный ответ: чтобы выразить эту строку в исходном коде Java, вам действительно нужно написать: String str = "SELECT * FROM my_table WHERE my_col like 'ABC_\\' ESCAPE '\\'"; Обратная косая черта должна быть экранирована, поскольку они являются escape-символом в исходном строковом литерале Java. - person Sean Owen; 22.07.2011
comment
На самом деле я запускаю это на Mac, поэтому эффективно Unix. Запуск внутри Eclipse и с терминала (unix CLI) дает тот же результат. Я понимаю об экранировании escape-символа в экземпляре String в исходном коде Java, я просто пытался показать сравнение один к одному. - person Jason Holmberg; 23.07.2011
comment
@Jason: Если вы работаете в терминале, я ожидаю, что оболочка будет обрабатывать обратную косую черту как escape-символ. Не могли бы вы показать свою точную командную строку? (Работая внутри Eclipse, я понимаю, что это несколько другое.) - person Jon Skeet; 23.07.2011
comment
@Jon: Вот моя точная командная строка: java org.jason.string.EscapeTest SELECT * FROM my_table WHERE my_col like 'ABC_\' ESCAPE '\' - person Jason Holmberg; 23.07.2011
comment
@Jon: вот точная командная строка java org.jason.string.EscapeTest "SELECT * FROM my_table WHERE my_col like 'ABC_\' ESCAPE '\'" - person Jason Holmberg; 23.07.2011
comment
@Jason: Это должны быть двойные кавычки, избегающие обратной косой черты. Я думал, что это делают только одинарные кавычки, но я никак не могу вспомнить подробности экранирования bash... - person Jon Skeet; 23.07.2011