@Aoeu

Bash как экранировать символы?

В общем не могу разобраться, кучу времени уже убил. Вот синтетический пример:
$ echo '123\n456' | sed 's/5/\\n/'
123\n4\n6
$ cat myecho
#!/bin/bash
str=`echo '123\n456' | sed 's/5/\\n/'`
echo $str
$ ./myecho
123\n4 6

У одной и той же команды разный вывод в зависимости от того из скрипта она выполняется или из консоли. Никак не пойму почему. Сделать чтоб вывод был тот же я могу добавив ещё 2 слэша в сед, вот так: sed 's/5/\\\\n/' но я не понимаю почему надо так делать и почему не работает без этого.

Update
Из мана к bash:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

Обратные кавычки считаются устаревшими, при их использовании бэкслэши обрабатываются как обычные символы, кроме тех случаев когда за ними идут $, ` или \. При использовании скобок всё выполняется как в консоли.
  • Вопрос задан
  • 37420 просмотров
Решения вопроса 1
В первом случае sed получает два слэша
Во втором случае двойной слэш обрабатывается СНАЧАЛА оператором обратных кавычек, т.е становится одним и sed получает ОДИН слэш, поэтому надо добавлять ещё два \\
Можно вместо `........` использовать $(..........), тогда будет работать как в первом случае
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
CityCat4
@CityCat4
//COPY01 EXEC PGM=IEBGENER
Потому что консоль при обработке ввода еще раз обрабатывает экранирование.

sed 's/5/\\\\n/' - при обработке ввода четыре символа \\\\ превращаются в два (каждый первый - экранирующй, каждый второй - экранируемый). При обработке команды два символа \\ превращаются в один. Вопрос экранирования пожалуй один из самый запутанных - иногда приходится экранировать по два и даже три раза!
Ответ написан
@krypt3r
echo -en '123\n456' | sed 's/5/\n/'
Ответ написан
@rv9ufz
Кратко о себе
Если выполнить скрипт с -x, то получается:

++ echo '123\n456'
++ sed 's/5/\n/'
+ str='123\n4
6'
+ echo '123\n4' 6
123\n4 6


Т.е. второй \n, полученный в результате обработки sed'ом, почему-то интерпретируется как перенос строки, а вот почему, навскидку непонятно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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