Почему sudo -i, а не sudo, удаляет символы новой строки? [дубликат]

Есть не одна проблема, видно по скрипту из ваших примеров:

#!/bin/sh
MSG="this is MAJOR stuff"
echo "$MSG" | sed -e 's/\(.*MAJOR.*\)/\o033[93m\1\o033[39m/'
echo "$MSG" | sed -e 's/\(.*MAJOR.*\)/\033[40;5;95;38;5;202\033[0m/'
echo "$MSG" | sed -e 's/\(.*MAJOR.*\)/\o033[40;5;95;38;5;202\o033[0m/'
echo "$MSG" | sed -e 's/\(.*MAJOR.*\)/\033[38;5;202\033[0m/'

который выдает (^[ - escape):

^[[93mthis is MAJOR stuff^[[39m
this is MAJOR stuff33[40;5;95;38;5;202this is MAJOR stuff33[0m
^[[40;5;95;38;5;202^[[0m
this is MAJOR stuff33[38;5;202this is MAJOR stuff33[0m

В первой строке, ^[[93m - aixterm 16-color escape для установки желтого текста, а ^39m сбрасывает текст к цветам терминала по умолчанию.

Вторая строка имеет проблемы с не завершенной последовательностью escape (которая начинает с установки фона на black=40, blink=5, 95=яркий пурпурный текст, затем 38 и 5 пытаются ввести 256-цветную последовательность - которая не завершается).

Третья строка является небольшой вариацией второй.

Основная проблема в том, что ваш sed не выдает управляющий символ, если вы не выразите его как \o033 (что вы сделали в нескольких местах).

Во-вторых, вы неправильно заканчиваете побеги. Последняя m является частью последовательности. Если последний символ отсутствует, вся последовательность может быть отброшена. Лучше всего прочитать документацию: Последовательности управления XTerm.

Кстати, ANSI никогда не документировал ничего больше 8 цветов, поэтому менее запутанно называть последовательности по оригинальной реализации (aixterm для 16-цветных, xterm для 256-цветных).

Если вы просто хотите, чтобы все строки с MAJOR были выделены оранжевым цветом, то (основываясь на комментариях) вы могли бы сделать так:

sed -e 's/^\(.*MAJOR.*\)$/\o033[48;5;95m\1\o033[m/'

Однако, код 5 менее широко поддерживается, чем 2 с использованием R/G/B, что-то вроде этого:

sed -e 's/^\(.*MAJOR.*\)$/\o033[48;2;128;128;0m\1\o033[m/'

(128-е - это только первая попытка - ваши вкусы могут варьироваться).

Further reading:

CSI Pm m Character Attributes (SGR).

11
03.06.2018, 15:09
2 ответа

Ejecutar eso sudo -i echo $'line1\nline2'bajo strace muestra que Bash comienza así:

9183  execve("/bin/bash", ["-bash", "--login", "-c", "echo line1\\\nline2\\\n"],...

Ahora, stracepresenta caracteres especiales con una barra invertida -cuando muestra las cadenas, por lo que lo que Bash realmente obtiene como argumento para -ces echo line1[backslash][newline]line2[backslash][newline]y para el shell, una barra invertida al final de una línea marca una línea de continuación y elimina la barra invertida y la nueva línea siguiente.

Sin -i, sudoejecuta echodirectamente, sin atravesar el caparazón:

9189  execve("/bin/echo", ["echo", "line1\nline2\n"],... 

Aquí, esa es una nueva línea literal que va a echo, y echolo imprime debidamente.


La ​​idea aquí debe ser que sudointente agregar una capa de escape de shell para acomodar el hecho de que sh -ctoma una única cadena , mientras que sudotoma el comando como distinto argumentos.

Compare los siguientes casos:

sudoescapa del espacio (este es solo el nombre del comando, ¡sin argumentos!):

$ sudo -i 'echo foo'
-bash: echo foo: command not found

sudoescapa de la barra invertida, por lo que esto realmente funciona (Bash's echono procesa la barra invertida):

$ sudo -i echo 'foo\bar'
foo\bar

Lo mismo con una pestaña:

$ sudo -i echo $'foo\tbar'
foo     bar

Aquí, no hay comillas adicionales en la barra invertida, por lo que Bash lo elimina mientras procesa la línea de comando de shell(bno es un carácter especial para el shell,y no necesita cotización. Esto es básicamente lo mismo quebash -c 'echo foo"b"ar'):

$ bash -c 'echo foo\bar'
foobar

El problema es que no se puede escapar de una nueva línea con una barra invertida, y sudono parece tener eso en cuenta.

En cualquier caso, citar problemas como este probablemente sea un poco más fácil si almacena los comandos que desea en un archivo y lo ejecuta como un script.

11
27.01.2020, 19:58

Podrías cambiar la estructura del comando:

echo "echo \"line1${n}line2${n}\"" | sudo -i bash -s

De esta manera sudono ve el argumento y por lo tanto no puede estropearlo.

2
27.01.2020, 19:58

Теги

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