Какой самый простой способ заменить конечную обратную косую черту \ на \ n?

Мне нужны многострочные строки в java, поэтому я ищу простой препроцессор для преобразования многострочных строк в стиле C в отдельные строки с литералом '\ n'.

До:

    System.out.println("convert trailing backslashes\
this is on another line\
\
\
above are two blank lines\
But don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");

После:

     System.out.println("convert trailing backslashes\nthis is on another line\n\n\nabove are two blank lines\nBut don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");

Я думал, что sed с этим справится, но sed основан на строках, поэтому замена символа '\' и следующей за ним новой строки (фактическое объединение двух строк) в sed не очень естественна. Я адаптировал единый лайнер sredden79 к следующему - работает, умно, но непонятно:

sed ':a { $!N; s/\\\n/\\n/; ta }'

Заменить escaped literal backslash, newline на escaped literal backslash, n. :a - это метка, а ta - метка перехода, если замена нашла совпадение; $ означает последнюю строку, а $! - противоположную (т.е. все строки, кроме последней). N означает добавление следующей строки в пространство шаблона (таким образом, делая видимым символ \n).

ИЗМЕНИТЬ здесь вариант, чтобы номера строк ошибок компилятора и т. Д. Были точными: он превращает каждую расширенную строку в "..."+\n (и правильно обрабатывает первую и последнюю строки строки):

sed ':a { $!N; s/\\\n/\\n"+\n"/; ta }'

давая:

    System.out.println("convert trailing backslashes\n"+
"this is on another line\n"+
"\n"+
"\n"+
"above are two blank lines\n"+
"But don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");

РЕДАКТИРОВАТЬ На самом деле, было бы лучше иметь многострочность в стиле Perl / Python, где она начинается и заканчивается специальным кодом в одной строке ("" "для python, я думаю).

Есть ли более простой, разумный и понятный способ (возможно, без использования sed)?


person 13ren    schedule 09.02.2010    source источник
comment
Если вы сделаете это, вы убьете поддержку своих инструментов. Внезапно ни одна среда IDE не будет правильно выделять синтаксис, отладчики будут отображать номера строк, отличные от номера вашего (исходного) исходного файла ... Помните, что компилятор (во время компиляции) объединит литеральные строки, объединенные с +, поэтому просто закройте строку, написание + и открытие его в следующей строке устраняет необходимость в препроцессоре и сохраняет поддержку вашего инструмента. FWIW.   -  person T.J. Crowder    schedule 09.02.2010


Ответы (4)


Однострочный Perl:

perl -0777 -pe 's/\\\n/\\n/g'

Это прочитает либо стандартный ввод, либо файл (ы), названные в его честь в командной строке, и запишет вывод в стандартный вывод.

Если вы используете редактор, который поддерживает фильтрацию, например vi или emacs, просто отфильтруйте текст с помощью указанной выше команды, и все готово:

Если вы используете Windows и вам нужно беспокоиться о \r:

C:\> perl -0777 -pe "s/\\\r?\n/\\n/g"

хотя я думаю, что Win32 Perl обрабатывает \r сам, поэтому в этом нет необходимости.

Параметр -0777 - это частный случай параметра -0 (это ноль), который определяет разделитель строк или записей. В данном случае это означает, что нам не нужен разделитель, поэтому читайте весь файл как одну строку.

Параметр -pe представляет собой комбинацию -p (построчно обрабатывать и распечатывать результат) и -e (следующий аргумент - (строка) программы для выполнения)

person Adrian Pronk    schedule 09.02.2010

Есть более простой, разумный и понятный способ.

Забудьте о препроцессоре, живите с ограничением, жалуйтесь на него (чтобы он, возможно, был исправлен в Java 7 или 8) и использовать IDE, чтобы облегчить боль.

Другие альтернативы (я полагаю, слишком хлопотно, но все же лучше, чем возиться с процессом компиляции):

  • используйте язык на основе JVM, который поддерживает здесь-документы
  • преобразовать строку в файл ресурсов
person Thilo    schedule 09.02.2010
comment
Спасибо 1. Идея IDE хороша, но не помогает с редактированием (редактировать, добавлять, перемещаться между строками многострочных конкатенированных строк - это то, что я использовал раньше). 2. Экстернализация в файл ресурсов - это то, чем я сейчас занимаюсь, но я думаю, что проще и удобнее иметь его вместе с исходным кодом, к которому он относится. 3. Совершенно новый язык JVM для решения этой проблемы кажется проблематичным, но ... он уже был бы отлажен и т. Д. И имел бы поддержку инструментов, подсветку синтаксиса и т. Д., Так что ваша идея имеет интригующую элегантность! Конечно, можно рассматривать сценарий sed как сам язык JVM. - person 13ren; 09.02.2010

Сценарий Perl для того, о чем вы просили.

while (<>) {
    chomp;
    print $_;
    if (/\\$/) {
        print "n";
    } else {
        print "\n";
    }
}
person Lachlan Roche    schedule 09.02.2010

sed 's/\x5c\x5c$/\x22\x5c\x5cn\x22/'

Hex для обратной косой черты и двойной кавычки - это \ x5c и \ x22 соответственно - его нужно экранировать, чтобы \ x5c удвоился, а $ привязал к концу строки.

Обновлен снова в соответствии с комментарием OP:

sed "{:a;N;\$!b a};s/\x5c\x5c\n/\x5c\x5cn/g" 

: A создает метку, а N добавляет строку в пространство шаблона, b a разветвляется обратно к метке: a, кроме случаев, когда это последняя строка $ !;

После того, как все загружено - подстановка одной строки заменяет все вхождения символа новой строки \ n на литерал '\ n' с использованием шестнадцатеричного кода ascii \ x5c для обратной косой черты.

person Community    schedule 29.12.2014
comment
Это не соединяет строки (и добавляет кавычки, которые не нужны). Попробуйте это на примере, приведенном в вопросе, и сравните результат, чтобы понять, что я имею в виду. - person 13ren; 30.12.2014
comment
Думаю, я ответил слишком быстро, я добавил обновление к своему ответу. Sed работает со строкой, завершающейся новой строкой, поэтому вы не можете изменять промежутки, если не перенаправляете их в пространство шаблонов. - person ; 30.12.2014
comment
Это очень похоже на решение sed, о котором уже идет речь. Кроме того, вы можете просто избежать обратной косой черты, которая более читабельна, чем шестнадцатеричная. Но вы, кажется, разбираетесь в sed - возможно, вы сможете придумать более четкую версию (это был фактический вопрос). Но я не уверен, что он есть, просто из-за необходимости соединять строки (или объединять их в пространстве шаблонов, как вы это описываете). Может быть, просто сделать это в двухступенчатом конвейере, первый соединяет все, а второй выполняет фактическое совпадение? В любом случае, прочтите весь вопрос и приступайте к делу! - person 13ren; 01.01.2015
comment
Понятно, если вы знаете sed в том смысле, что в нем нет ничего лишнего - чтобы сделать его читаемым для тех, кто не знает sed так хорошо, и, как правило, вы можете комментировать везде, где вам нужно использовать конструкции, которые могут показаться загадочными. для тех, кто не очень хорошо разбирается в жаргоне соответствующих программных инструментов. Я использую шестнадцатеричный код, потому что я только что закончил писать инструмент переименования, который использует sed alot для замены специальных символов в именах файлов. Если вам нужен достойный инструмент переименования, вы можете проверить его здесь: scriptsandoneliners.blogspot.com/2014/12/ - person ; 01.01.2015
comment
Ничего лишнего, как самое короткое, не значит самое ясное. ОШИБКА: он не соответствует завершающей обратной косой черте (т.е. _1 _ \\\ n). Hexcodes hide such errors because less clear. Using '' not " не требует выхода в долларах (\$), что более понятно. Я люблю sed, но быстро забываю синтаксис, так что это плохое вложение ( для меня). На данный момент этот ответ менее ясен, чем тот, который я дал в самом вопросе. Но мне нравится, как вы соединяете строки, и только потом делаете подпункт - может быть менее эффективным (?), но более четким. - person 13ren; 03.01.2015
comment
Ого, извините, пример в вопросе не демонстрирует ошибку, которую я имел в виду !: другие строки следует оставить как есть (без обратной косой черты в конце). - person 13ren; 03.01.2015
comment
Я думаю, что однострочник в вашем OP, вероятно, немного медленнее для больших наборов данных, потому что он должен выполнять вызовы для замены на каждом проходе. Объем используемого пространства шаблонов одинаков, потому что они оба просто N (добавляются к пространству шаблонов), добавляя его в конец. Тем не менее, в ответе, который я написал, он будет выполнять только один однопроходный вызов замены по сравнению с одним вызовом на новую строку в тексте. Чтобы оболочка интерпретировала шестнадцатеричный код, вам нужно использовать двойные кавычки, но он также захочет интерпретировать $ как переменную оболочки, поэтому он экранирован. - person ; 03.01.2015
comment
Этот вопрос требует самого ясного, а не самого быстрого. В этом ответе новая строка заменяется литералом \n во всех строках, а не только в строках с обратной косой чертой в конце. - person 13ren; 05.01.2015
comment
sed {: a; N; \ $! ba}; s / \ x5c \ x5c \ n / \ x5cn / g Я вижу, больше шестнадцатеричного кода выполняет свою работу - приведенный вами пример не подчеркивает разницу, поскольку все они имеют завершающие обратная косая черта. Выглядит неясно, но несколько комментариев выше, и это не только понятно, но и поучительно! знак равно - person ; 05.01.2015