Bash 4.2 en CentOS 6.5:
En mi ~/.bash_profile
tengo un montón de alias, que incluyen:
alias grep='grep -n --color=always'
para poder resaltar el color e imprimir números de línea automáticamente cuando se ejecuta grep
. Si ejecuto lo siguiente, resaltar funciona como se esperaba:
$ grep -Re 'regex_here' *.py
Sin embargo, cuando ejecuté esto recientemente:
$ find . -name '*.py' | xargs grep -E 'regex_here'
los resultados no se resaltaron y los números de línea no se imprimieron, lo que me obligó a retroceder y agregar explícitamente -n --color=always
al grep
comando.
- ¿
xargs
No lee alias en el entorno? - Si no, ¿hay alguna manera de hacerlo?
xargs
comando. Lo que estoy tratando de averiguar es si hay una forma desde la que pueda llamar directamente a mi aliasxargs
.export GREP_OPTIONS='-n --color=always'
antes tu comando xargs?.bash_profile
. Siéntase libre de escribir una respuesta ...Respuestas:
Un alias es interno al shell donde se define. No es visible para otros procesos. Lo mismo ocurre con las funciones de shell.
xargs
es una aplicación separada, que no es un shell, por lo que no tiene un concepto de alias o funciones.Puede hacer que xargs invoque un shell en lugar de invocarlo
grep
directamente. Sin embargo, invocar un shell no es suficiente, también debe definir el alias en ese shell. Si el alias está definido en su.bashrc
, puede obtener ese archivo; sin embargo, esto puede no funcionar,.bashrc
realiza otras tareas que no tienen sentido en un shell no interactivo.Tenga cuidado con las complejidades de las citas anidadas al escribir la expresión regular. Puede simplificar su vida pasando la expresión regular como parámetro al shell.
Puede realizar la búsqueda de alias explícitamente. Entonces
xargs
ya veremosgrep -n --color=always
.En zsh:
Por cierto, tenga en cuenta que se
find … | xargs …
rompe en los nombres de archivo que contienen espacios (entre otros) . Puede solucionar esto cambiando a registros delimitados por nulos:o usando
-exec
:En lugar de llamar
find
, puede hacer todo por completo dentro del shell. El patrón global**/
atraviesa directorios de forma recursiva. En bash,shopt -s globstar
primero debe ejecutar para habilitar este patrón global.Esto tiene algunas limitaciones:
**/
repite en enlaces simbólicos a directorios.Otro enfoque es utilizar la sustitución de procesos, como lo sugiere MariusMatutiae .
Esto es útil cuando
**/
no es aplicable: parafind
expresiones complejas , o en bash ≤4.2 cuando no desea recurrir bajo enlaces simbólicos. Tenga en cuenta que esto se rompe en los nombres de archivos que contienen espacios; Una solución alternativa es establecerIFS
y deshabilitar el globbing , pero está empezando a ser un poco complejo:fuente
Utilizar
alias xargs='xargs '
fuente
sudo
...Tome esto como una demostración de otro enfoque, que no puedo encontrar en la pregunta SO relacionada :
Puede escribir una función de contenedor para la
xargs
que comprueba si el primer argumento es un alias y, de ser así, expandirlo en consecuencia.Aquí hay un código que hace exactamente eso, pero desafortunadamente requiere el shell Z y, por lo tanto, no se ejecuta 1: 1 con bash (y, francamente, no estoy acostumbrado a bash lo suficiente como para portarlo):
Prueba de que funciona:
fuente
Una solución más simple y elegante es utilizar la sustitución de procesos :
No crea un nuevo shell como lo hace la tubería, lo que significa que todavía está en su shell original donde se define el alias, y la salida es exactamente lo que desea que sea.
Solo tenga cuidado de no dejar espacio entre la redirección y el paréntesis, de lo contrario bash arrojará un error. A lo mejor de mi conocimiento, la sustitución del proceso es apoyada por Bash, Zsh, Ksh {88,93}, pero no por pdksh (me han dicho que debería ser un todavía no ).
fuente
find
comandos, aunque es necesario tener cuidado con que se va a romper en espacios, y que no se puede arreglar tan fácilmente comofind | xargs
puede ser (por el cambio a-print0
y-0
, o el uso-exec
). Cuando corresponde,**/
es más simple y más robusto.grep leerá un conjunto de opciones predeterminadas de la variable de entorno GREP_OPTIONS. Si vas a poner
en su .bashrc, la variable se pasará a subcapas y obtendrá los resultados que espera.
fuente
--line-number
ni ingrese--color=always
aGREP_OPTIONS
menos que sea solo para un comando, esto romperá muchos scripts.--color=auto
está bien tener allí, y eso es todo. Poner esta línea en tu.bashrc
romperá muchas cosas./etc/init.d/cron
de mi sistema:value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2`
. Oa partir de/usr/bin/pdfjam
:pdftitl=`printf "%s" "$PDFinfo" | grep -e … | sed -e …`
. Un alias no es un problema ya que no se ve en los scripts.GREP_OPTIONS
rompe la previsibilidad muy mal, excepto por algunas opciones como--color=auto
(para lo que fue diseñada).