Если единственное, в чем вы можете быть уверены, так это в том, что вам нужна строка цифр после 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
Para el caso específico
echo run after_bundle
no es necesario citar.No se necesitan comillas porque el argumento de echo
son 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:
echo
a 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 echo
y ejecutarlos nuevamente.
Su comando echo run after_bundle
puede 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 echo
así, 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.)
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 echo
contiene 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 echo
o cualquier otro comando, el problema no está en echo
sino 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 echo
con $'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á 詜 reboot
en una configuración regional que usa GB18030 o GBK, 唰 reboot
en 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 reboot
porque 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 uname
en 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$
(uname
se 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 zsh
y 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, echo
también se pasa como argumento a la utilidad echo
(para decirle cómo se invocó ), es argv[0]
y argc
es 3, aunque en la mayoría de los shells hoy en día echo
está incorporado, por lo que el shell simula exec()
de un archivo /bin/echo
con 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.SJIS
de 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.