Опасно ли запускать эхо без кавычек?

Если единственное, в чем вы можете быть уверены, так это в том, что вам нужна строка цифр после 47.1.1.1.1.13. , вы можете использовать одно из:

grep -Po '47\.1\.1\.1\.1\.13.\K\d+'
sed -n 's/.*47\.1\.1\.1\.1\.13\.\([0-9]\+\).*/\1/p'
perl -lne '/47\.1\.1\.1\.1\.13\.(\d+)/ && print $1'

Если, как в вашем примере, целевая строка всегда перед STRING , вы можете использовать:

grep -Po '\d+(?= STRING)' 
sed -n 's/.*\.\([0-9]\+\) STRING.*/\1/p' 
perl -lne '/(\d+)(?= STRING)/ && print $1'

В качестве альтернативы, если целевая строка всегда является первое появление точки, строки чисел и пробела, которые вы показываете в своем вопросе, вы можете сделать:

grep -Po '^\S+\.\K\d+' 
sed -n 's/^[^ \t]*\.\([0-9]\+\).*/\1/p'
perl -lne '/^\S+\.(\d+)/ && print $1' file
11
17.05.2018, 13:57
2 ответа

Para el caso específico

echo run after_bundle

no es necesario citar.No se necesitan comillas porque el argumento de echoson ​​cadenas estáticas que no contienen expansiones de variables ni sustituciones de comandos, etc. Son "solo dos palabras" (y, como Stéphane señala , se construyen adicionalmente fuera delconjunto de caracteres portátiles).

El "peligro" surge cuando se trata de datos variables que el shell puede expandir o interpretar. En tales casos, se debe tener cuidado de que el shell haga lo correcto y que el resultado sea el esperado.

Las siguientes dos preguntas contienen información relevante al respecto:


echoa veces se usa para "proteger" comandos potencialmente dañinos en las respuestas de este sitio. Por ejemplo, puedo mostrar cómo eliminar archivos o mover archivos a un nuevo destino usando

echo rm "${name##*/}.txt"

o

echo mv "$name" "/new_dir/$newname"

Esto generaría comandos en el terminal en lugar de eliminar o cambiar el nombre de los archivos. Luego, el usuario podría inspeccionar los comandos, decidir que se ven bien, eliminar el echoy ejecutarlos nuevamente.

Su comando echo run after_bundlepuede ser una instrucción para el usuario, o puede ser un fragmento de código "comentado" que es demasiado peligroso para ejecutar sin conocer las consecuencias.

Usando echoasí, uno tiene que saber qué hace el comando modificado y uno debe garantizar que el comando modificado realmente es seguro (potencialmente no si contenía redirecciones y usarlo en una canalización no funciona, etc.)

19
27.01.2020, 19:56

Solo una nota adicional además de la excelente respuesta de @Kusalananda .

echo run after_bundle

está bien porque ninguno de los caracteres en esos 3 argumentos¹ pasados ​​a echocontiene caracteres que son especiales para el shell.

Y (el punto adicional que quiero resaltar aquí )no hay una configuración regional del sistema donde esos bytes puedan traducirse en caracteres que son especiales para el shell.

Todos esos caracteres están en lo que POSIX llama el conjunto de caracteres portátiles. Esos caracteres deben estar presentes y codificados de la misma manera en todos los conjuntos de caracteres en un sistema POSIX².

Entonces, esa línea de comando se interpretará de la misma manera, independientemente de la configuración regional.

Ahora, si comenzamos a usar caracteres fuera de ese conjunto de caracteres portátiles, es una buena idea citarlos incluso si no son especiales para el shell, porque en otra configuración regional, los bytes que los constituyen pueden interpretarse como caracteres diferentes. que podría volverse especial para el caparazón. Tenga en cuenta que si está usando echoo cualquier otro comando, el problema no está en echosino en cómo el shell analiza su código.

Por ejemplo en un UTF -8:

echo voilà | iconv -f UTF-8 -t //TRANSLIT

Ese àestá codificado como 0xc3 0xa0. Ahora, si tiene esa línea de código en un script de shell y el script de shell es invocado por un usuario que usa una configuración regional cuyo conjunto de caracteres no es UTF -8, esos dos bytes podrían crear caracteres muy diferentes.

Por ejemplo, en una configuración regional fr_FR.ISO8859-15, una configuración regional francesa típica que usa el conjunto de caracteres estándar de un solo byte -que cubre el idioma francés (, el mismo que se usa para la mayoría de los idiomas de Europa occidental, incluido el inglés ),ese byte 0xc3 se interpreta como el carácter Ãy 0xa0 como el carácter de espacio sin interrupción -.

Y en algunos sistemas como NetBSD³, ese espacio que no es -se considera como un carácter en blanco (isblank()y devuelve verdadero, se compara con[[:blank:]])y shells como bash] por lo tanto, trátelo como un delimitador de token en su sintaxis.

Eso significa que en lugar de ejecutar echocon $'voil\xc3\xa0'como argumento, lo ejecutan con $'voil\xc3'como argumento, lo que significa que no imprimirá voilàcorrectamente.

Se pone mucho peor con conjuntos de caracteres chinos como BIG5, BIG5 -HKSCS, GB18030, GBK que tienen muchos caracteres cuya codificación contiene la misma codificación que |, `,\(para nombrar el peor)(también ese ridículo SJIS, también conocido como Microsoft Kanji, excepto que es ¥en lugar de \, pero aún así la mayoría de las herramientas lo tratan como \ya que está codificado como 0x5c allí ).

Por ejemplo, si en una configuración regional china zh_CN.gb18030, escribe un script como:

echo 詜 reboot

Ese script generará 詜 rebooten una configuración regional que usa GB18030 o GBK, 唰 rebooten una configuración regional que usa BIG5 o BIG5 -HKSCS, pero en una configuración regional C que usa ASCII o una configuración regional que usa ISO8859 -15 o UTF -8, hará que se ejecute rebootporque la codificación GB18030 de es 0xd4 0x7c y 0x7c es la codificación de |en ASCII, por lo que terminamos ejecutando:

 echo �| reboot

(que � que representa, sin embargo, el byte 0xd4 se representa en la configuración regional ). Ejemplo usando el menos dañino unameen lugar dereboot:

$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash./myscript | sed -n l
Linux$

(unamese ejecutó ).

Así que mi consejo sería citar todas las cadenas que contienen caracteres fuera del conjunto de caracteres portátil.

Sin embargo, tenga en cuenta que dado que la codificación de \y `se encuentran en la codificación de algunos de esos caracteres, es mejor no usar \o "..."o$'...'(dentro del cual `y /o \siguen siendo especiales ),pero el '...'en lugar de citar caracteres fuera del conjunto de caracteres portátiles.

No conozco ningún sistema que tenga una configuración regional en la que el conjunto de caracteres tenga algún carácter (que no sea ', por supuesto )cuya codificación contenga la codificación de ', por lo que esos '...'definitivamente debería ser el más seguro.

Tenga en cuenta que varios shells también admiten una notación $'\uXXXX'para expresar caracteres en función de su punto de código Unicode. En shells como zshy bash, el carácter se inserta codificado en el conjunto de caracteres de la configuración regional (, aunque puede causar comportamientos inesperados si ese conjunto de caracteres no tiene ese carácter ). Eso le permite evitar insertar caracteres no -ASCII en su código de shell.

Entonces arriba:

echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'

o:

echo $'voil\u00e0'
echo $'\u8a5c reboot'

(con la advertencia de que podría romper el script cuando se ejecuta en entornos locales que no tienen esos caracteres ).

O mejor, ya que \también es especial paraecho(o al menos algunas implementaciones echo, al menos las compatibles con Unix):

printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'

(tenga en cuenta que \también es especial en el primer argumento de printf, por lo que es mejor evitar los caracteres ASCII que no sean -en caso de que puedan contener la codificación de\).

Tenga en cuenta que también podría hacer:

'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'

(eso sería exagerado, pero podría darle tranquilidad si no está seguro de qué caracteres están en el conjunto de caracteres portátiles)

También asegúrese de nunca usar la forma antigua `...`de sustitución de comando (que introduce otro nivel de procesamiento de barra invertida ), sino que use $(...)en su lugar.


¹ técnicamente, echotambién se pasa como argumento a la utilidad echo(para decirle cómo se invocó ), es argv[0]y argces 3, aunque en la mayoría de los shells hoy en día echoestá incorporado, por lo que el shell simula exec()de un archivo /bin/echocon una lista de 3 argumentos.También es común considerar que la lista de argumentos comienza con el segundo(argv[1]aargv[argc - 1])ya que es sobre los que actúan principalmente los comandos.

² ¡una excepción notable a eso es la configuración regional ridícula ja_JP.SJISde los sistemas FreeBSD cuyo conjunto de caracteres no tiene caracteres \ni ~!

³ tenga en cuenta que mientras muchos sistemas (FreeBSD, Solaris, no GNU )consideran U+00A0 como [[:blank:]]en UTF -8 locales, pocos lo hacen en otros locales como aquellos que usan ISO8859 -15, posiblemente para evitar este tipo de problema.

27
27.01.2020, 19:56

Теги

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